Changeset 58459 in vbox for trunk/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/Shell
- Timestamp:
- Oct 28, 2015 8:17:18 PM (9 years ago)
- Location:
- trunk/src/VBox/Devices/EFI/Firmware
- Files:
-
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/EFI/Firmware
-
Property svn:mergeinfo
set to (toggle deleted branches)
/vendor/edk2/current 103735-103757
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/Shell/ConsoleLogger.c
r48674 r58459 2 2 Provides interface to shell console logger. 3 3 4 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR> 4 Copyright (c) 2013 Hewlett-Packard Development Company, L.P. 5 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR> 5 6 This program and the accompanying materials 6 7 are licensed and made available under the terms and conditions of the BSD License … … 12 13 **/ 13 14 14 #include "ConsoleLogger.h"15 15 #include "Shell.h" 16 17 STATIC CONST CHAR16 mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };18 16 19 17 /** … … 474 472 ; Index++ 475 473 ){ 476 *(ConsoleInfo->Attributes + (CopySize/sizeof(ConsoleInfo->Attributes )) + Index) = ConsoleInfo->HistoryMode.Attribute;474 *(ConsoleInfo->Attributes + (CopySize/sizeof(ConsoleInfo->Attributes[0])) + Index) = ConsoleInfo->HistoryMode.Attribute; 477 475 } 478 476 … … 644 642 FreePool(Resp); 645 643 ShellInfoObject.ConsoleInfo->Enabled = FALSE; 644 // 645 // When user wants to quit, the shell should stop running the command. 646 // 647 gBS->SignalEvent (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak); 646 648 return (EFI_DEVICE_ERROR); 647 649 } else { … … 818 820 ) 819 821 { 820 EFI_INPUT_KEY Key; 821 UINTN EventIndex; 822 CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo; 822 EFI_STATUS Status; 823 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TxtInEx; 824 EFI_KEY_DATA KeyData; 825 UINTN EventIndex; 826 CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo; 827 823 828 ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This); 824 829 if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) { … … 826 831 } 827 832 ASSERT(ShellInfoObject.ConsoleInfo == ConsoleInfo); 828 if (ShellInfoObject.HaltOutput) { 829 // 830 // just get some key 831 // 832 gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex); 833 gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); 834 ShellInfoObject.HaltOutput = FALSE; 835 } 833 834 Status = gBS->HandleProtocol (gST->ConsoleInHandle, &gEfiSimpleTextInputExProtocolGuid, (VOID **) &TxtInEx); 835 if (!EFI_ERROR (Status)) { 836 while (ShellInfoObject.HaltOutput) { 837 838 ShellInfoObject.HaltOutput = FALSE; 839 // 840 // just get some key 841 // 842 Status = gBS->WaitForEvent (1, &TxtInEx->WaitForKeyEx, &EventIndex); 843 ASSERT_EFI_ERROR (Status); 844 Status = TxtInEx->ReadKeyStrokeEx (TxtInEx, &KeyData); 845 if (EFI_ERROR(Status)) { 846 break; 847 } 848 849 if ((KeyData.Key.UnicodeChar == L's') && (KeyData.Key.ScanCode == SCAN_NULL) && 850 ((KeyData.KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID | EFI_LEFT_CONTROL_PRESSED)) || 851 (KeyData.KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID | EFI_RIGHT_CONTROL_PRESSED)) 852 ) 853 ) { 854 ShellInfoObject.HaltOutput = TRUE; 855 } 856 } 857 } 858 836 859 if (!ShellInfoObject.ConsoleInfo->Enabled) { 837 860 return (EFI_DEVICE_ERROR); … … 1029 1052 // 1030 1053 if (!EFI_ERROR (Status)) { 1031 Screen = &ConsoleInfo->Buffer[(ConsoleInfo->ColsPerScreen + 1) * ConsoleInfo->CurrentStartRow];1054 Screen = &ConsoleInfo->Buffer[(ConsoleInfo->ColsPerScreen + 2) * ConsoleInfo->CurrentStartRow]; 1032 1055 Attributes = &ConsoleInfo->Attributes[ConsoleInfo->ColsPerScreen * ConsoleInfo->CurrentStartRow]; 1033 1056 for ( Row = ConsoleInfo->OriginalStartRow … … 1047 1070 // Skip the NULL on each column end in text buffer only 1048 1071 // 1049 Screen ++;1072 Screen += 2; 1050 1073 } 1051 1074 ConsoleInfo->HistoryMode.CursorColumn = 0; -
trunk/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/Shell/ConsoleLogger.h
r48674 r58459 15 15 #define _CONSOLE_LOGGER_HEADER_ 16 16 17 #include <Uefi.h> 18 19 #include <Protocol/SimpleTextOut.h> 20 #include <Protocol/EfiShell.h> 21 #include <Protocol/EfiShellParameters.h> 22 23 #include <Library/DebugLib.h> 24 #include <Library/BaseLib.h> 25 #include <Library/BaseMemoryLib.h> 26 #include <Library/MemoryAllocationLib.h> 27 #include <Library/UefiBootServicesTableLib.h> 28 #include <Library/HiiLib.h> 29 #include <Library/ShellLib.h> 17 #include "Shell.h" 30 18 31 19 #define CONSOLE_LOGGER_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('c', 'o', 'P', 'D') -
trunk/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/Shell/ConsoleWrappers.c
r48674 r58459 2 2 Function definitions for shell simple text in and out on top of file handles. 3 3 4 Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR> 4 Copyright (c) 2013 Hewlett-Packard Development Company, L.P. 5 Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR> 5 6 This program and the accompanying materials 6 7 are licensed and made available under the terms and conditions of the BSD License … … 13 14 **/ 14 15 15 #include <Uefi.h>16 #include <ShellBase.h>17 18 #include "ConsoleWrappers.h"19 16 #include "Shell.h" 20 17 … … 23 20 SHELL_FILE_HANDLE FileHandle; 24 21 EFI_HANDLE TheHandle; 22 UINT64 RemainingBytesOfInputFile; 25 23 } SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL; 26 24 … … 29 27 SHELL_FILE_HANDLE FileHandle; 30 28 EFI_HANDLE TheHandle; 29 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *OriginalSimpleTextOut; 31 30 } SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL; 32 31 … … 46 45 ) 47 46 { 48 UINT64 Position; 49 UINT64 Size; 50 // 51 // Someone is waiting on the keystroke event, if there's 52 // a key pending, signal the event 53 // 54 // Context is the pointer to EFI_SIMPLE_TEXT_INPUT_PROTOCOL 55 // 56 ShellInfoObject.NewEfiShellProtocol->GetFilePosition(((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)Context)->FileHandle, &Position); 57 ShellInfoObject.NewEfiShellProtocol->GetFileSize (((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)Context)->FileHandle, &Size ); 58 if (Position < Size) { 59 gBS->SignalEvent (Event); 60 } 47 gBS->SignalEvent (Event); 61 48 } 62 49 … … 95 82 { 96 83 UINTN Size; 97 Size = sizeof(CHAR16); 84 85 // 86 // Verify the parameters 87 // 98 88 if (Key == NULL || This == NULL) { 99 89 return (EFI_INVALID_PARAMETER); 100 90 } 91 92 // 93 // Check if we have any characters left in the stream. 94 // 95 if (((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)This)->RemainingBytesOfInputFile == 0) { 96 return (EFI_NOT_READY); 97 } 98 99 Size = sizeof(CHAR16); 100 101 // 102 // Decrement the amount of free space by Size or set to zero (for odd length files) 103 // 104 if (((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)This)->RemainingBytesOfInputFile > Size) { 105 ((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)This)->RemainingBytesOfInputFile -= Size; 106 } else { 107 ((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)This)->RemainingBytesOfInputFile = 0; 108 } 109 101 110 Key->ScanCode = 0; 102 111 return (ShellInfoObject.NewEfiShellProtocol->ReadFile( … … 125 134 SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ProtocolToReturn; 126 135 EFI_STATUS Status; 136 UINT64 CurrentPosition; 137 UINT64 FileSize; 127 138 128 139 if (HandleLocation == NULL || FileHandleToUse == NULL) { … … 134 145 return (NULL); 135 146 } 136 ProtocolToReturn->FileHandle = FileHandleToUse; 147 148 ShellGetFileSize (FileHandleToUse, &FileSize); 149 ShellGetFilePosition(FileHandleToUse, &CurrentPosition); 150 151 // 152 // Initialize the protocol members 153 // 154 ProtocolToReturn->RemainingBytesOfInputFile = FileSize - CurrentPosition; 155 ProtocolToReturn->FileHandle = FileHandleToUse; 137 156 ProtocolToReturn->SimpleTextIn.Reset = FileBasedSimpleTextInReset; 138 157 ProtocolToReturn->SimpleTextIn.ReadKeyStroke = FileBasedSimpleTextInReadKeyStroke; … … 258 277 ) 259 278 { 260 return (EFI_UNSUPPORTED); 279 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *PassThruProtocol; 280 281 PassThruProtocol = ((SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)This)->OriginalSimpleTextOut; 282 283 // Pass the QueryMode call thru to the original SimpleTextOutProtocol 284 return (PassThruProtocol->QueryMode( 285 PassThruProtocol, 286 ModeNumber, 287 Columns, 288 Rows)); 261 289 } 262 290 … … 391 419 SHELL_FILE_HANDLE to support redirecting output from a file. 392 420 393 @param[in] FileHandleToUse The pointer to the SHELL_FILE_HANDLE to use. 394 @param[in] HandleLocation The pointer of a location to copy handle with protocol to. 421 @param[in] FileHandleToUse The pointer to the SHELL_FILE_HANDLE to use. 422 @param[in] HandleLocation The pointer of a location to copy handle with protocol to. 423 @param[in] OriginalProtocol The pointer to the original output protocol for pass thru of functions. 395 424 396 425 @retval NULL There was insufficient memory available. … … 400 429 EFIAPI 401 430 CreateSimpleTextOutOnFile( 402 IN SHELL_FILE_HANDLE FileHandleToUse, 403 IN EFI_HANDLE *HandleLocation 431 IN SHELL_FILE_HANDLE FileHandleToUse, 432 IN EFI_HANDLE *HandleLocation, 433 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *OriginalProtocol 404 434 ) 405 435 { … … 416 446 } 417 447 ProtocolToReturn->FileHandle = FileHandleToUse; 448 ProtocolToReturn->OriginalSimpleTextOut = OriginalProtocol; 418 449 ProtocolToReturn->SimpleTextOut.Reset = FileBasedSimpleTextOutReset; 419 450 ProtocolToReturn->SimpleTextOut.TestString = FileBasedSimpleTextOutTestString; … … 430 461 return (NULL); 431 462 } 432 ProtocolToReturn->SimpleTextOut.Mode->MaxMode = 0;433 ProtocolToReturn->SimpleTextOut.Mode->Mode = 0;434 ProtocolToReturn->SimpleTextOut.Mode->Attribute = 0;435 ProtocolToReturn->SimpleTextOut.Mode->CursorColumn = 0;436 ProtocolToReturn->SimpleTextOut.Mode->CursorRow = 0;437 ProtocolToReturn->SimpleTextOut.Mode->CursorVisible = FALSE;463 ProtocolToReturn->SimpleTextOut.Mode->MaxMode = OriginalProtocol->Mode->MaxMode; 464 ProtocolToReturn->SimpleTextOut.Mode->Mode = OriginalProtocol->Mode->Mode; 465 ProtocolToReturn->SimpleTextOut.Mode->Attribute = OriginalProtocol->Mode->Attribute; 466 ProtocolToReturn->SimpleTextOut.Mode->CursorColumn = OriginalProtocol->Mode->CursorColumn; 467 ProtocolToReturn->SimpleTextOut.Mode->CursorRow = OriginalProtocol->Mode->CursorRow; 468 ProtocolToReturn->SimpleTextOut.Mode->CursorVisible = OriginalProtocol->Mode->CursorVisible; 438 469 439 470 Status = gBS->InstallProtocolInterface( -
trunk/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/Shell/ConsoleWrappers.h
r48674 r58459 2 2 Function definitions for shell simple text in and out on top of file handles. 3 3 4 Copyright (c) 2013 Hewlett-Packard Development Company, L.P. 4 5 Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR> 5 6 This program and the accompanying materials … … 51 52 SHELL_FILE_HANDLE to support redirecting output from a file. 52 53 53 @param[in] FileHandleToUse The pointer to the SHELL_FILE_HANDLE to use. 54 @param[in] HandleLocation The pointer of a location to copy handle with protocol to. 54 @param[in] FileHandleToUse The pointer to the SHELL_FILE_HANDLE to use. 55 @param[in] HandleLocation The pointer of a location to copy handle with protocol to. 56 @param[in] OriginalProtocol The pointer to the original output protocol for pass thru of functions. 55 57 56 58 @retval NULL There was insufficient memory available. … … 60 62 EFIAPI 61 63 CreateSimpleTextOutOnFile( 62 IN SHELL_FILE_HANDLE FileHandleToUse, 63 IN EFI_HANDLE *HandleLocation 64 IN SHELL_FILE_HANDLE FileHandleToUse, 65 IN EFI_HANDLE *HandleLocation, 66 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *OriginalProtocol 64 67 ); 65 68 -
trunk/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/Shell/FileHandleWrappers.c
r48674 r58459 3 3 StdIn, StdOut, StdErr, etc...). 4 4 5 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR> 5 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR> 6 Copyright (c) 2013, Hewlett-Packard Development Company, L.P. 6 7 This program and the accompanying materials 7 8 are licensed and made available under the terms and conditions of the BSD License … … 417 418 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); 418 419 if (EFI_ERROR (Status)) { 419 continue;420 break; 420 421 } 421 422 … … 509 510 Cwd = ShellInfoObject.NewEfiShellProtocol->GetCurDir(NULL); 510 511 if (Cwd != NULL) { 511 Str Cpy(TabStr, Cwd);512 StrnCpy(TabStr, Cwd, (*BufferSize)/sizeof(CHAR16) - 1); 512 513 if (TabStr[StrLen(TabStr)-1] == L'\\' && *(CurrentString + TabPos) == L'\\' ) { 513 514 TabStr[StrLen(TabStr)-1] = CHAR_NULL; … … 515 516 StrnCat(TabStr, CurrentString + TabPos, (StringLen - TabPos) * sizeof (CHAR16)); 516 517 } else { 517 StrCpy(TabStr, L"");518 *TabStr = CHAR_NULL; 518 519 StrnCat(TabStr, CurrentString + TabPos, (StringLen - TabPos) * sizeof (CHAR16)); 519 520 } 520 521 } else { 521 Str Cpy(TabStr, CurrentString + TabPos);522 StrnCpy(TabStr, CurrentString + TabPos, (*BufferSize)/sizeof(CHAR16) - 1); 522 523 } 523 Str Cat(TabStr, L"*");524 StrnCat(TabStr, L"*", (*BufferSize)/sizeof(CHAR16) - 1 - StrLen(TabStr)); 524 525 FoundFileList = NULL; 525 // TabStr = PathCleanUpDirectories(TabStr);526 526 Status = ShellInfoObject.NewEfiShellProtocol->FindFiles(TabStr, &FoundFileList); 527 527 for ( TempStr = CurrentString … … 849 849 ASSERT(FoundFileList == NULL); 850 850 851 return EFI_SUCCESS;851 return Status; 852 852 } 853 853 … … 951 951 ) 952 952 { 953 VOID* NewBuffer; 954 UINTN NewSize; 955 EFI_STATUS Status; 956 957 // 958 // Most if not all UEFI commands will have an '\r\n' at the end of any output. 959 // Since the output was redirected to a variable, it does not make sense to 960 // keep this. So, before closing, strip the trailing '\r\n' from the variable 961 // if it exists. 962 // 963 NewBuffer = NULL; 964 NewSize = 0; 965 966 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer); 967 if (Status == EFI_BUFFER_TOO_SMALL) { 968 NewBuffer = AllocateZeroPool(NewSize + sizeof(CHAR16)); 969 if (NewBuffer == NULL) { 970 return EFI_OUT_OF_RESOURCES; 971 } 972 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer); 973 } 974 975 if (!EFI_ERROR(Status) && NewBuffer != NULL) { 976 977 if (StrSize(NewBuffer) > 6) 978 { 979 if ((((CHAR16*)NewBuffer)[(StrSize(NewBuffer)/2) - 2] == CHAR_LINEFEED) 980 && (((CHAR16*)NewBuffer)[(StrSize(NewBuffer)/2) - 3] == CHAR_CARRIAGE_RETURN)) { 981 ((CHAR16*)NewBuffer)[(StrSize(NewBuffer)/2) - 3] = CHAR_NULL; 982 } 983 984 if (IsVolatileEnv(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name)) { 985 Status = SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, StrSize(NewBuffer), NewBuffer); 986 } else { 987 Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, StrSize(NewBuffer), NewBuffer); 988 } 989 } 990 } 991 992 SHELL_FREE_NON_NULL(NewBuffer); 953 993 FreePool((EFI_FILE_PROTOCOL_ENVIRONMENT*)This); 954 return ( EFI_SUCCESS);994 return (Status); 955 995 } 956 996 … … 1101 1141 { 1102 1142 EFI_FILE_PROTOCOL_ENVIRONMENT *EnvFileInterface; 1143 UINTN EnvNameSize; 1103 1144 1104 1145 if (EnvName == NULL) { … … 1109 1150 // Get some memory 1110 1151 // 1111 EnvFileInterface = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_ENVIRONMENT)+StrSize(EnvName)); 1152 EnvNameSize = StrSize(EnvName); 1153 EnvFileInterface = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_ENVIRONMENT)+EnvNameSize); 1112 1154 if (EnvFileInterface == NULL){ 1113 1155 return (NULL); … … 1127 1169 EnvFileInterface->Delete = FileInterfaceEnvDelete; 1128 1170 EnvFileInterface->Read = FileInterfaceEnvRead; 1129 1130 StrCpy(EnvFileInterface->Name, EnvName);1171 1172 CopyMem(EnvFileInterface->Name, EnvName, EnvNameSize); 1131 1173 1132 1174 // -
trunk/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/Shell/Shell.c
r48674 r58459 2 2 This is THE shell (application) 3 3 4 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR> 4 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR> 5 (C) Copyright 2013-2014, Hewlett-Packard Development Company, L.P. 5 6 This program and the accompanying materials 6 7 are licensed and made available under the terms and conditions of the BSD License … … 24 25 FALSE, 25 26 { 26 0, 27 0, 28 0, 29 0, 30 0, 31 0, 32 0, 33 0, 34 0, 27 {{ 28 0, 29 0, 30 0, 31 0, 32 0, 33 0, 34 0, 35 0, 36 0 37 }}, 35 38 0, 36 39 NULL, 37 40 NULL 38 41 }, 39 { 0,0},42 {{NULL, NULL}, NULL}, 40 43 { 41 { 0,0},44 {{NULL, NULL}, NULL}, 42 45 0, 43 46 0, … … 51 54 NULL, 52 55 NULL, 53 {0,0,NULL,NULL}, 54 {0,0}, 56 {{NULL, NULL}, NULL, NULL}, 57 {{NULL, NULL}, NULL, NULL}, 58 NULL, 59 NULL, 60 NULL, 61 NULL, 55 62 NULL, 56 63 NULL, … … 63 70 STATIC CONST CHAR16 mExecutableExtensions[] = L".NSH;.EFI"; 64 71 STATIC CONST CHAR16 mStartupScript[] = L"startup.nsh"; 72 73 /** 74 Cleans off leading and trailing spaces and tabs. 75 76 @param[in] String pointer to the string to trim them off. 77 **/ 78 EFI_STATUS 79 EFIAPI 80 TrimSpaces( 81 IN CHAR16 **String 82 ) 83 { 84 ASSERT(String != NULL); 85 ASSERT(*String!= NULL); 86 // 87 // Remove any spaces and tabs at the beginning of the (*String). 88 // 89 while (((*String)[0] == L' ') || ((*String)[0] == L'\t')) { 90 CopyMem((*String), (*String)+1, StrSize((*String)) - sizeof((*String)[0])); 91 } 92 93 // 94 // Remove any spaces and tabs at the end of the (*String). 95 // 96 while ((StrLen (*String) > 0) && (((*String)[StrLen((*String))-1] == L' ') || ((*String)[StrLen((*String))-1] == L'\t'))) { 97 (*String)[StrLen((*String))-1] = CHAR_NULL; 98 } 99 100 return (EFI_SUCCESS); 101 } 102 103 /** 104 Parse for the next instance of one string within another string. Can optionally make sure that 105 the string was not escaped (^ character) per the shell specification. 106 107 @param[in] SourceString The string to search within 108 @param[in] FindString The string to look for 109 @param[in] CheckForEscapeCharacter TRUE to skip escaped instances of FinfString, otherwise will return even escaped instances 110 **/ 111 CHAR16* 112 EFIAPI 113 FindNextInstance( 114 IN CONST CHAR16 *SourceString, 115 IN CONST CHAR16 *FindString, 116 IN CONST BOOLEAN CheckForEscapeCharacter 117 ) 118 { 119 CHAR16 *Temp; 120 if (SourceString == NULL) { 121 return (NULL); 122 } 123 Temp = StrStr(SourceString, FindString); 124 125 // 126 // If nothing found, or we dont care about escape characters 127 // 128 if (Temp == NULL || !CheckForEscapeCharacter) { 129 return (Temp); 130 } 131 132 // 133 // If we found an escaped character, try again on the remainder of the string 134 // 135 if ((Temp > (SourceString)) && *(Temp-1) == L'^') { 136 return FindNextInstance(Temp+1, FindString, CheckForEscapeCharacter); 137 } 138 139 // 140 // we found the right character 141 // 142 return (Temp); 143 } 144 145 /** 146 Check whether the string between a pair of % is a valid envifronment variable name. 147 148 @param[in] BeginPercent pointer to the first percent. 149 @param[in] EndPercent pointer to the last percent. 150 151 @retval TRUE is a valid environment variable name. 152 @retval FALSE is NOT a valid environment variable name. 153 **/ 154 BOOLEAN 155 IsValidEnvironmentVariableName( 156 IN CONST CHAR16 *BeginPercent, 157 IN CONST CHAR16 *EndPercent 158 ) 159 { 160 CONST CHAR16 *Walker; 161 162 Walker = NULL; 163 164 ASSERT (BeginPercent != NULL); 165 ASSERT (EndPercent != NULL); 166 ASSERT (BeginPercent < EndPercent); 167 168 if ((BeginPercent + 1) == EndPercent) { 169 return FALSE; 170 } 171 172 for (Walker = BeginPercent + 1; Walker < EndPercent; Walker++) { 173 if ( 174 (*Walker >= L'0' && *Walker <= L'9') || 175 (*Walker >= L'A' && *Walker <= L'Z') || 176 (*Walker >= L'a' && *Walker <= L'z') || 177 (*Walker == L'_') 178 ) { 179 if (Walker == BeginPercent + 1 && (*Walker >= L'0' && *Walker <= L'9')) { 180 return FALSE; 181 } else { 182 continue; 183 } 184 } else { 185 return FALSE; 186 } 187 } 188 189 return TRUE; 190 } 191 192 /** 193 Determine if a command line contains a split operation 194 195 @param[in] CmdLine The command line to parse. 196 197 @retval TRUE CmdLine has a valid split. 198 @retval FALSE CmdLine does not have a valid split. 199 **/ 200 BOOLEAN 201 EFIAPI 202 ContainsSplit( 203 IN CONST CHAR16 *CmdLine 204 ) 205 { 206 CONST CHAR16 *TempSpot; 207 CONST CHAR16 *FirstQuote; 208 CONST CHAR16 *SecondQuote; 209 210 FirstQuote = FindNextInstance (CmdLine, L"\"", TRUE); 211 SecondQuote = NULL; 212 TempSpot = FindFirstCharacter(CmdLine, L"|", L'^'); 213 214 if (FirstQuote == NULL || 215 TempSpot == NULL || 216 TempSpot == CHAR_NULL || 217 FirstQuote > TempSpot 218 ) { 219 return (BOOLEAN) ((TempSpot != NULL) && (*TempSpot != CHAR_NULL)); 220 } 221 222 while ((TempSpot != NULL) && (*TempSpot != CHAR_NULL)) { 223 if (FirstQuote == NULL || FirstQuote > TempSpot) { 224 break; 225 } 226 SecondQuote = FindNextInstance (FirstQuote + 1, L"\"", TRUE); 227 if (SecondQuote == NULL) { 228 break; 229 } 230 if (SecondQuote < TempSpot) { 231 FirstQuote = FindNextInstance (SecondQuote + 1, L"\"", TRUE); 232 continue; 233 } else { 234 FirstQuote = FindNextInstance (SecondQuote + 1, L"\"", TRUE); 235 TempSpot = FindFirstCharacter(TempSpot + 1, L"|", L'^'); 236 continue; 237 } 238 } 239 240 return (BOOLEAN) ((TempSpot != NULL) && (*TempSpot != CHAR_NULL)); 241 } 65 242 66 243 /** … … 125 302 &KeyData, 126 303 NotificationFunction, 127 &ShellInfoObject.CtrlSNotifyHandle 2);304 &ShellInfoObject.CtrlSNotifyHandle3); 128 305 } 129 306 KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED; … … 133 310 &KeyData, 134 311 NotificationFunction, 135 &ShellInfoObject.CtrlSNotifyHandle 2);312 &ShellInfoObject.CtrlSNotifyHandle4); 136 313 } 137 314 return (Status); … … 237 414 } 238 415 if (ShellInfoObject.HiiHandle == NULL) { 239 return (EFI_NOT_STARTED); 416 Status = EFI_NOT_STARTED; 417 goto FreeResources; 240 418 } 241 419 } … … 267 445 // Check the command line 268 446 // 269 Status = ProcessCommandLine(); 447 Status = ProcessCommandLine (); 448 if (EFI_ERROR (Status)) { 449 goto FreeResources; 450 } 270 451 271 452 // … … 291 472 gST->ConOut->Mode->CursorRow, 292 473 NULL, 293 STRING_TOKEN (STR_VER_OUTPUT_MAIN ),474 STRING_TOKEN (STR_VER_OUTPUT_MAIN_SHELL), 294 475 ShellInfoObject.HiiHandle, 295 476 SupportLevel[PcdGet8(PcdShellSupportLevel)], 296 477 gEfiShellProtocol->MajorVersion, 297 gEfiShellProtocol->MinorVersion, 478 gEfiShellProtocol->MinorVersion 479 ); 480 481 ShellPrintHiiEx ( 482 -1, 483 -1, 484 NULL, 485 STRING_TOKEN (STR_VER_OUTPUT_MAIN_SUPPLIER), 486 ShellInfoObject.HiiHandle, 487 (CHAR16 *) PcdGetPtr (PcdShellSupplier) 488 ); 489 490 ShellPrintHiiEx ( 491 -1, 492 -1, 493 NULL, 494 STRING_TOKEN (STR_VER_OUTPUT_MAIN_UEFI), 495 ShellInfoObject.HiiHandle, 298 496 (gST->Hdr.Revision&0xffff0000)>>16, 299 497 (gST->Hdr.Revision&0x0000ffff), … … 376 574 } 377 575 378 if (!Shell CommandGetExit() && (PcdGet8(PcdShellSupportLevel) >= 3 || PcdGetBool(PcdShellForceConsole)) && !EFI_ERROR(Status) && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) {576 if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit && !ShellCommandGetExit() && (PcdGet8(PcdShellSupportLevel) >= 3 || PcdGetBool(PcdShellForceConsole)) && !EFI_ERROR(Status) && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) { 379 577 // 380 578 // begin the UI waiting loop … … 393 591 // 394 592 ShellInfoObject.PageBreakEnabled = PcdGetBool(PcdShellPageBreakDefault); 593 ASSERT (ShellInfoObject.ConsoleInfo != NULL); 395 594 ShellInfoObject.ConsoleInfo->Enabled = TRUE; 396 595 ShellInfoObject.ConsoleInfo->RowCounter = 0; … … 415 614 } 416 615 616 FreeResources: 417 617 // 418 618 // uninstall protocols / free memory / etc... … … 436 636 if (ShellInfoObject.NewEfiShellProtocol != NULL){ 437 637 if (ShellInfoObject.NewEfiShellProtocol->IsRootShell()){ 438 ShellInfoObject.NewEfiShellProtocol->SetEnv(L"cwd", L"", TRUE);638 InternalEfiShellSetEnv(L"cwd", NULL, TRUE); 439 639 } 440 640 CleanUpShellProtocol(ShellInfoObject.NewEfiShellProtocol); … … 627 827 } 628 828 629 STATIC CONST SHELL_PARAM_ITEM mShellParamList[] = {630 {L"-nostartup", TypeFlag},631 {L"-startup", TypeFlag},632 {L"-noconsoleout", TypeFlag},633 {L"-noconsolein", TypeFlag},634 {L"-nointerrupt", TypeFlag},635 {L"-nomap", TypeFlag},636 {L"-noversion", TypeFlag},637 {L"-startup", TypeFlag},638 {L"-delay", TypeValue},639 {NULL, TypeMax}640 };641 642 829 /** 643 830 Process all Uefi Shell 2.0 command line options. … … 673 860 ) 674 861 { 675 EFI_STATUS Status; 676 LIST_ENTRY *Package; 677 UINTN Size; 678 CONST CHAR16 *TempConst; 679 UINTN Count; 680 UINTN LoopVar; 681 CHAR16 *ProblemParam; 682 UINT64 Intermediate; 683 684 Package = NULL; 685 ProblemParam = NULL; 686 687 Status = ShellCommandLineParse (mShellParamList, &Package, NULL, FALSE); 688 689 Count = 1; 690 Size = 0; 691 TempConst = ShellCommandLineGetRawValue(Package, Count++); 692 if (TempConst != NULL && StrLen(TempConst)) { 693 ShellInfoObject.ShellInitSettings.FileName = AllocateZeroPool(StrSize(TempConst)); 694 if (ShellInfoObject.ShellInitSettings.FileName == NULL) { 695 return (EFI_OUT_OF_RESOURCES); 696 } 697 StrCpy(ShellInfoObject.ShellInitSettings.FileName, TempConst); 698 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = 1; 699 for (LoopVar = 0 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) { 700 if (StrCmp(gEfiShellParametersProtocol->Argv[LoopVar], ShellInfoObject.ShellInitSettings.FileName)==0) { 701 LoopVar++; 702 // 703 // We found the file... add the rest of the params... 704 // 705 for ( ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) { 706 ASSERT((ShellInfoObject.ShellInitSettings.FileOptions == NULL && Size == 0) || (ShellInfoObject.ShellInitSettings.FileOptions != NULL)); 707 StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions, 708 &Size, 709 L" ", 710 0); 711 if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) { 712 SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName); 713 return (EFI_OUT_OF_RESOURCES); 714 } 715 StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions, 716 &Size, 717 gEfiShellParametersProtocol->Argv[LoopVar], 718 0); 719 if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) { 720 SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName); 721 return (EFI_OUT_OF_RESOURCES); 722 } 862 UINTN Size; 863 UINTN LoopVar; 864 CHAR16 *CurrentArg; 865 CHAR16 *DelayValueStr; 866 UINT64 DelayValue; 867 EFI_STATUS Status; 868 EFI_UNICODE_COLLATION_PROTOCOL *UnicodeCollation; 869 870 // `file-name-options` will contain arguments to `file-name` that we don't 871 // know about. This would cause ShellCommandLineParse to error, so we parse 872 // arguments manually, ignoring those after the first thing that doesn't look 873 // like a shell option (which is assumed to be `file-name`). 874 875 Status = gBS->LocateProtocol ( 876 &gEfiUnicodeCollationProtocolGuid, 877 NULL, 878 (VOID **) &UnicodeCollation 879 ); 880 if (EFI_ERROR (Status)) { 881 return Status; 882 } 883 884 // Set default options 885 ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup = FALSE; 886 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = FALSE; 887 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut = FALSE; 888 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn = FALSE; 889 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt = FALSE; 890 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap = FALSE; 891 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion = FALSE; 892 ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay = FALSE; 893 ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit = FALSE; 894 ShellInfoObject.ShellInitSettings.Delay = 5; 895 896 // 897 // Start LoopVar at 0 to parse only optional arguments at Argv[0] 898 // and parse other parameters from Argv[1]. This is for use case that 899 // UEFI Shell boot option is created, and OptionalData is provided 900 // that starts with shell command-line options. 901 // 902 for (LoopVar = 0 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) { 903 CurrentArg = gEfiShellParametersProtocol->Argv[LoopVar]; 904 if (UnicodeCollation->StriColl ( 905 UnicodeCollation, 906 L"-startup", 907 CurrentArg 908 ) == 0) { 909 ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup = TRUE; 910 } 911 else if (UnicodeCollation->StriColl ( 912 UnicodeCollation, 913 L"-nostartup", 914 CurrentArg 915 ) == 0) { 916 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = TRUE; 917 } 918 else if (UnicodeCollation->StriColl ( 919 UnicodeCollation, 920 L"-noconsoleout", 921 CurrentArg 922 ) == 0) { 923 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut = TRUE; 924 } 925 else if (UnicodeCollation->StriColl ( 926 UnicodeCollation, 927 L"-noconsolein", 928 CurrentArg 929 ) == 0) { 930 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn = TRUE; 931 } 932 else if (UnicodeCollation->StriColl ( 933 UnicodeCollation, 934 L"-nointerrupt", 935 CurrentArg 936 ) == 0) { 937 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt = TRUE; 938 } 939 else if (UnicodeCollation->StriColl ( 940 UnicodeCollation, 941 L"-nomap", 942 CurrentArg 943 ) == 0) { 944 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap = TRUE; 945 } 946 else if (UnicodeCollation->StriColl ( 947 UnicodeCollation, 948 L"-noversion", 949 CurrentArg 950 ) == 0) { 951 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion = TRUE; 952 } 953 else if (UnicodeCollation->StriColl ( 954 UnicodeCollation, 955 L"-delay", 956 CurrentArg 957 ) == 0) { 958 ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay = TRUE; 959 // Check for optional delay value following "-delay" 960 DelayValueStr = gEfiShellParametersProtocol->Argv[LoopVar + 1]; 961 if (DelayValueStr != NULL){ 962 if (*DelayValueStr == L':') { 963 DelayValueStr++; 723 964 } 724 } 725 } 726 } else { 727 ShellCommandLineFreeVarList(Package); 728 Package = NULL; 729 Status = ShellCommandLineParse (mShellParamList, &Package, &ProblemParam, FALSE); 730 if (EFI_ERROR(Status)) { 731 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), ShellInfoObject.HiiHandle, ProblemParam); 732 FreePool(ProblemParam); 733 ShellCommandLineFreeVarList(Package); 734 return (EFI_INVALID_PARAMETER); 735 } 736 } 737 738 ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup = ShellCommandLineGetFlag(Package, L"-startup"); 739 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = ShellCommandLineGetFlag(Package, L"-nostartup"); 740 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut = ShellCommandLineGetFlag(Package, L"-noconsoleout"); 741 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn = ShellCommandLineGetFlag(Package, L"-noconsolein"); 742 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt = ShellCommandLineGetFlag(Package, L"-nointerrupt"); 743 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap = ShellCommandLineGetFlag(Package, L"-nomap"); 744 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion = ShellCommandLineGetFlag(Package, L"-noversion"); 745 ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay = ShellCommandLineGetFlag(Package, L"-delay"); 746 747 ShellInfoObject.ShellInitSettings.Delay = 5; 748 965 if (!EFI_ERROR(ShellConvertStringToUint64 ( 966 DelayValueStr, 967 &DelayValue, 968 FALSE, 969 FALSE 970 ))) { 971 ShellInfoObject.ShellInitSettings.Delay = (UINTN)DelayValue; 972 LoopVar++; 973 } 974 } 975 } else if (UnicodeCollation->StriColl ( 976 UnicodeCollation, 977 L"-_exit", 978 CurrentArg 979 ) == 0) { 980 ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit = TRUE; 981 } else if (StrnCmp (L"-", CurrentArg, 1) == 0) { 982 // Unrecognised option 983 ShellPrintHiiEx(-1, -1, NULL, 984 STRING_TOKEN (STR_GEN_PROBLEM), 985 ShellInfoObject.HiiHandle, 986 CurrentArg 987 ); 988 return EFI_INVALID_PARAMETER; 989 } else { 990 // 991 // First argument should be Shell.efi image name 992 // 993 if (LoopVar == 0) { 994 continue; 995 } 996 997 ShellInfoObject.ShellInitSettings.FileName = AllocateCopyPool(StrSize(CurrentArg), CurrentArg); 998 if (ShellInfoObject.ShellInitSettings.FileName == NULL) { 999 return (EFI_OUT_OF_RESOURCES); 1000 } 1001 // 1002 // We found `file-name`. 1003 // 1004 ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = 1; 1005 LoopVar++; 1006 1007 // Add `file-name-options` 1008 for (Size = 0 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) { 1009 ASSERT((ShellInfoObject.ShellInitSettings.FileOptions == NULL && Size == 0) || (ShellInfoObject.ShellInitSettings.FileOptions != NULL)); 1010 StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions, 1011 &Size, 1012 L" ", 1013 0); 1014 if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) { 1015 SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName); 1016 return (EFI_OUT_OF_RESOURCES); 1017 } 1018 StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions, 1019 &Size, 1020 gEfiShellParametersProtocol->Argv[LoopVar], 1021 0); 1022 if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) { 1023 SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName); 1024 return (EFI_OUT_OF_RESOURCES); 1025 } 1026 } 1027 } 1028 } 1029 1030 // "-nointerrupt" overrides "-delay" 749 1031 if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt) { 750 1032 ShellInfoObject.ShellInitSettings.Delay = 0; 751 } else if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay) { 752 TempConst = ShellCommandLineGetValue(Package, L"-delay"); 753 if (TempConst != NULL && *TempConst == L':') { 754 TempConst++; 755 } 756 if (TempConst != NULL && !EFI_ERROR(ShellConvertStringToUint64(TempConst, &Intermediate, FALSE, FALSE))) { 757 ShellInfoObject.ShellInitSettings.Delay = (UINTN)Intermediate; 758 } 759 } 760 ShellCommandLineFreeVarList(Package); 761 762 return (Status); 1033 } 1034 1035 return EFI_SUCCESS; 763 1036 } 764 1037 … … 776 1049 EFIAPI 777 1050 DoStartupScript( 778 EFI_DEVICE_PATH_PROTOCOL *ImagePath,779 EFI_DEVICE_PATH_PROTOCOL *FilePath1051 IN EFI_DEVICE_PATH_PROTOCOL *ImagePath, 1052 IN EFI_DEVICE_PATH_PROTOCOL *FilePath 780 1053 ) 781 1054 { … … 807 1080 return (EFI_OUT_OF_RESOURCES); 808 1081 } 809 Str Cpy(FileStringPath, ShellInfoObject.ShellInitSettings.FileName);1082 StrnCpy(FileStringPath, ShellInfoObject.ShellInitSettings.FileName, NewSize/sizeof(CHAR16) -1); 810 1083 if (ShellInfoObject.ShellInitSettings.FileOptions != NULL) { 811 Str Cat(FileStringPath, L" ");812 Str Cat(FileStringPath, ShellInfoObject.ShellInitSettings.FileOptions);1084 StrnCat(FileStringPath, L" ", NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1); 1085 StrnCat(FileStringPath, ShellInfoObject.ShellInitSettings.FileOptions, NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1); 813 1086 } 814 1087 Status = RunCommand(FileStringPath); … … 828 1101 } 829 1102 1103 gST->ConOut->EnableCursor(gST->ConOut, FALSE); 830 1104 // 831 1105 // print out our warning and see if they press a key 832 1106 // 833 for ( Status = EFI_UNSUPPORTED, Delay = ShellInfoObject.ShellInitSettings.Delay * 101107 for ( Status = EFI_UNSUPPORTED, Delay = ShellInfoObject.ShellInitSettings.Delay 834 1108 ; Delay != 0 && EFI_ERROR(Status) 835 1109 ; Delay-- 836 1110 ){ 837 ShellPrintHiiEx(0, gST->ConOut->Mode->CursorRow, NULL, STRING_TOKEN (STR_SHELL_STARTUP_QUESTION), ShellInfoObject.HiiHandle, Delay /10);838 gBS->Stall (100000 );1111 ShellPrintHiiEx(0, gST->ConOut->Mode->CursorRow, NULL, STRING_TOKEN (STR_SHELL_STARTUP_QUESTION), ShellInfoObject.HiiHandle, Delay); 1112 gBS->Stall (1000000); 839 1113 if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) { 840 1114 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); … … 842 1116 } 843 1117 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_CRLF), ShellInfoObject.HiiHandle); 1118 gST->ConOut->EnableCursor(gST->ConOut, TRUE); 844 1119 845 1120 // … … 887 1162 // 888 1163 if (!EFI_ERROR(Status) && FileHandle != NULL) { 889 Status = RunScriptFile Handle (FileHandle, mStartupScript);1164 Status = RunScriptFile (mStartupScript, FileHandle, L"", ShellInfoObject.NewShellParametersProtocol); 890 1165 ShellInfoObject.NewEfiShellProtocol->CloseFile(FileHandle); 891 1166 } else { … … 898 1173 ASSERT(FileHandle == NULL); 899 1174 } else { 900 Status = RunScriptFile(FileStringPath );1175 Status = RunScriptFile(FileStringPath, NULL, L"", ShellInfoObject.NewShellParametersProtocol); 901 1176 FreePool(FileStringPath); 902 1177 } … … 964 1239 CmdLine[BufferSize / sizeof (CHAR16)] = CHAR_NULL; 965 1240 Status = RunCommand(CmdLine); 966 }1241 } 967 1242 968 1243 // … … 1013 1288 Node = AllocateZeroPool(sizeof(BUFFER_LIST)); 1014 1289 ASSERT(Node != NULL); 1015 Node->Buffer = Allocate ZeroPool(StrSize(Buffer));1290 Node->Buffer = AllocateCopyPool(StrSize(Buffer), Buffer); 1016 1291 ASSERT(Node->Buffer != NULL); 1017 StrCpy(Node->Buffer, Buffer);1018 1292 1019 1293 InsertTailList(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link); … … 1046 1320 } 1047 1321 FreePool(*CommandString); 1048 *CommandString = Allocate ZeroPool(StrSize(NewString));1322 *CommandString = AllocateCopyPool(StrSize(NewString), NewString); 1049 1323 if (*CommandString == NULL) { 1050 1324 return (EFI_OUT_OF_RESOURCES); 1051 1325 } 1052 StrCpy(*CommandString, NewString); 1326 return (EFI_SUCCESS); 1327 } 1328 1329 /** 1330 This function will eliminate unreplaced (and therefore non-found) environment variables. 1331 1332 @param[in,out] CmdLine The command line to update. 1333 **/ 1334 EFI_STATUS 1335 EFIAPI 1336 StripUnreplacedEnvironmentVariables( 1337 IN OUT CHAR16 *CmdLine 1338 ) 1339 { 1340 CHAR16 *FirstPercent; 1341 CHAR16 *FirstQuote; 1342 CHAR16 *SecondPercent; 1343 CHAR16 *SecondQuote; 1344 CHAR16 *CurrentLocator; 1345 1346 for (CurrentLocator = CmdLine ; CurrentLocator != NULL ; ) { 1347 FirstQuote = FindNextInstance(CurrentLocator, L"\"", TRUE); 1348 FirstPercent = FindNextInstance(CurrentLocator, L"%", TRUE); 1349 SecondPercent = FirstPercent!=NULL?FindNextInstance(FirstPercent+1, L"%", TRUE):NULL; 1350 if (FirstPercent == NULL || SecondPercent == NULL) { 1351 // 1352 // If we ever dont have 2 % we are done. 1353 // 1354 break; 1355 } 1356 1357 if (FirstQuote!= NULL && FirstQuote < FirstPercent) { 1358 SecondQuote = FindNextInstance(FirstQuote+1, L"\"", TRUE); 1359 // 1360 // Quote is first found 1361 // 1362 1363 if (SecondQuote < FirstPercent) { 1364 // 1365 // restart after the pair of " 1366 // 1367 CurrentLocator = SecondQuote + 1; 1368 } else /* FirstPercent < SecondQuote */{ 1369 // 1370 // Restart on the first percent 1371 // 1372 CurrentLocator = FirstPercent; 1373 } 1374 continue; 1375 } 1376 1377 if (FirstQuote == NULL || SecondPercent < FirstQuote) { 1378 if (IsValidEnvironmentVariableName(FirstPercent, SecondPercent)) { 1379 // 1380 // We need to remove from FirstPercent to SecondPercent 1381 // 1382 CopyMem(FirstPercent, SecondPercent + 1, StrSize(SecondPercent + 1)); 1383 // 1384 // dont need to update the locator. both % characters are gone. 1385 // 1386 } else { 1387 CurrentLocator = SecondPercent + 1; 1388 } 1389 continue; 1390 } 1391 CurrentLocator = FirstQuote; 1392 } 1053 1393 return (EFI_SUCCESS); 1054 1394 } … … 1134 1474 1135 1475 // 1136 // Quick out if none were found...1137 //1138 if (NewSize == StrSize(OriginalCommandLine)) {1139 ASSERT(Temp == NULL);1140 Temp = StrnCatGrow(&Temp, NULL, OriginalCommandLine, 0);1141 return (Temp);1142 }1143 1144 //1145 1476 // now do the replacements... 1146 1477 // 1147 NewCommandLine1 = Allocate ZeroPool(NewSize);1478 NewCommandLine1 = AllocateCopyPool(NewSize, OriginalCommandLine); 1148 1479 NewCommandLine2 = AllocateZeroPool(NewSize); 1149 1480 ItemTemp = AllocateZeroPool(ItemSize+(2*sizeof(CHAR16))); … … 1154 1485 return (NULL); 1155 1486 } 1156 StrCpy(NewCommandLine1, OriginalCommandLine);1157 1487 for (MasterEnvList = EfiShellGetEnv(NULL) 1158 ; MasterEnvList != NULL && *MasterEnvList != CHAR_NULL //&& *(MasterEnvList+1) != CHAR_NULL1488 ; MasterEnvList != NULL && *MasterEnvList != CHAR_NULL 1159 1489 ; MasterEnvList += StrLen(MasterEnvList) + 1 1160 1490 ){ 1161 Str Cpy(ItemTemp, L"%");1162 Str Cat(ItemTemp, MasterEnvList);1163 Str Cat(ItemTemp, L"%");1491 StrnCpy(ItemTemp, L"%", ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16))-1); 1492 StrnCat(ItemTemp, MasterEnvList, ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16))-1 - StrLen(ItemTemp)); 1493 StrnCat(ItemTemp, L"%", ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16))-1 - StrLen(ItemTemp)); 1164 1494 ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, ItemTemp, EfiShellGetEnv(MasterEnvList), TRUE, FALSE); 1165 Str Cpy(NewCommandLine1, NewCommandLine2);1495 StrnCpy(NewCommandLine1, NewCommandLine2, NewSize/sizeof(CHAR16)-1); 1166 1496 } 1167 1497 if (CurrentScriptFile != NULL) { … … 1171 1501 ){ 1172 1502 ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, AliasListNode->Alias, AliasListNode->CommandString, TRUE, FALSE); 1173 StrCpy(NewCommandLine1, NewCommandLine2); 1174 } 1175 } 1176 1503 StrnCpy(NewCommandLine1, NewCommandLine2, NewSize/sizeof(CHAR16)-1); 1504 } 1505 } 1506 1507 // 1508 // Remove non-existant environment variables 1509 // 1510 StripUnreplacedEnvironmentVariables(NewCommandLine1); 1511 1512 // 1513 // Now cleanup any straggler intentionally ignored "%" characters 1514 // 1515 ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, L"^%", L"%", TRUE, FALSE); 1516 StrnCpy(NewCommandLine1, NewCommandLine2, NewSize/sizeof(CHAR16)-1); 1517 1177 1518 FreePool(NewCommandLine2); 1178 1519 FreePool(ItemTemp); … … 1225 1566 SHELL_FREE_NON_NULL(NextCommandLine); 1226 1567 return (EFI_OUT_OF_RESOURCES); 1227 } 1228 if (NextCommandLine[0] != CHAR_NULL && 1568 } else if (StrStr(OurCommandLine, L"|") != NULL || Size1 == 0 || Size2 == 0) { 1569 SHELL_FREE_NON_NULL(OurCommandLine); 1570 SHELL_FREE_NON_NULL(NextCommandLine); 1571 return (EFI_INVALID_PARAMETER); 1572 } else if (NextCommandLine[0] != CHAR_NULL && 1229 1573 NextCommandLine[0] == L'a' && 1230 1574 NextCommandLine[1] == L' ' … … 1247 1591 InsertHeadList(&ShellInfoObject.SplitList.Link, &Split->Link); 1248 1592 1249 ASSERT(StrStr(OurCommandLine, L"|") == NULL);1250 1593 Status = RunCommand(OurCommandLine); 1251 1594 … … 1290 1633 1291 1634 /** 1292 Function will process and run a command line. 1293 1294 This will determine if the command line represents an internal shell 1295 command or dispatch an external application. 1635 Take the original command line, substitute any variables, free 1636 the original string, return the modified copy. 1637 1638 @param[in] CmdLine pointer to the command line to update. 1639 1640 @retval EFI_SUCCESS the function was successful. 1641 @retval EFI_OUT_OF_RESOURCES a memory allocation failed. 1642 **/ 1643 EFI_STATUS 1644 EFIAPI 1645 ShellSubstituteVariables( 1646 IN CHAR16 **CmdLine 1647 ) 1648 { 1649 CHAR16 *NewCmdLine; 1650 NewCmdLine = ShellConvertVariables(*CmdLine); 1651 SHELL_FREE_NON_NULL(*CmdLine); 1652 if (NewCmdLine == NULL) { 1653 return (EFI_OUT_OF_RESOURCES); 1654 } 1655 *CmdLine = NewCmdLine; 1656 return (EFI_SUCCESS); 1657 } 1658 1659 /** 1660 Take the original command line, substitute any alias in the first group of space delimited characters, free 1661 the original string, return the modified copy. 1662 1663 @param[in] CmdLine pointer to the command line to update. 1664 1665 @retval EFI_SUCCESS the function was successful. 1666 @retval EFI_OUT_OF_RESOURCES a memory allocation failed. 1667 **/ 1668 EFI_STATUS 1669 EFIAPI 1670 ShellSubstituteAliases( 1671 IN CHAR16 **CmdLine 1672 ) 1673 { 1674 CHAR16 *NewCmdLine; 1675 CHAR16 *CommandName; 1676 EFI_STATUS Status; 1677 UINTN PostAliasSize; 1678 ASSERT(CmdLine != NULL); 1679 ASSERT(*CmdLine!= NULL); 1680 1681 1682 CommandName = NULL; 1683 if (StrStr((*CmdLine), L" ") == NULL){ 1684 StrnCatGrow(&CommandName, NULL, (*CmdLine), 0); 1685 } else { 1686 StrnCatGrow(&CommandName, NULL, (*CmdLine), StrStr((*CmdLine), L" ") - (*CmdLine)); 1687 } 1688 1689 // 1690 // This cannot happen 'inline' since the CmdLine can need extra space. 1691 // 1692 NewCmdLine = NULL; 1693 if (!ShellCommandIsCommandOnList(CommandName)) { 1694 // 1695 // Convert via alias 1696 // 1697 Status = ShellConvertAlias(&CommandName); 1698 if (EFI_ERROR(Status)){ 1699 return (Status); 1700 } 1701 PostAliasSize = 0; 1702 NewCmdLine = StrnCatGrow(&NewCmdLine, &PostAliasSize, CommandName, 0); 1703 if (NewCmdLine == NULL) { 1704 SHELL_FREE_NON_NULL(CommandName); 1705 SHELL_FREE_NON_NULL(*CmdLine); 1706 return (EFI_OUT_OF_RESOURCES); 1707 } 1708 NewCmdLine = StrnCatGrow(&NewCmdLine, &PostAliasSize, StrStr((*CmdLine), L" "), 0); 1709 if (NewCmdLine == NULL) { 1710 SHELL_FREE_NON_NULL(CommandName); 1711 SHELL_FREE_NON_NULL(*CmdLine); 1712 return (EFI_OUT_OF_RESOURCES); 1713 } 1714 } else { 1715 NewCmdLine = StrnCatGrow(&NewCmdLine, NULL, (*CmdLine), 0); 1716 } 1717 1718 SHELL_FREE_NON_NULL(*CmdLine); 1719 SHELL_FREE_NON_NULL(CommandName); 1720 1721 // 1722 // re-assign the passed in double pointer to point to our newly allocated buffer 1723 // 1724 *CmdLine = NewCmdLine; 1725 1726 return (EFI_SUCCESS); 1727 } 1728 1729 /** 1730 Takes the Argv[0] part of the command line and determine the meaning of it. 1731 1732 @param[in] CmdName pointer to the command line to update. 1733 1734 @retval Internal_Command The name is an internal command. 1735 @retval File_Sys_Change the name is a file system change. 1736 @retval Script_File_Name the name is a NSH script file. 1737 @retval Unknown_Invalid the name is unknown. 1738 @retval Efi_Application the name is an application (.EFI). 1739 **/ 1740 SHELL_OPERATION_TYPES 1741 EFIAPI 1742 GetOperationType( 1743 IN CONST CHAR16 *CmdName 1744 ) 1745 { 1746 CHAR16* FileWithPath; 1747 CONST CHAR16* TempLocation; 1748 CONST CHAR16* TempLocation2; 1749 1750 FileWithPath = NULL; 1751 // 1752 // test for an internal command. 1753 // 1754 if (ShellCommandIsCommandOnList(CmdName)) { 1755 return (Internal_Command); 1756 } 1757 1758 // 1759 // Test for file system change request. anything ending with first : and cant have spaces. 1760 // 1761 if (CmdName[(StrLen(CmdName)-1)] == L':') { 1762 if ( StrStr(CmdName, L" ") != NULL 1763 || StrLen(StrStr(CmdName, L":")) > 1 1764 ) { 1765 return (Unknown_Invalid); 1766 } 1767 return (File_Sys_Change); 1768 } 1769 1770 // 1771 // Test for a file 1772 // 1773 if ((FileWithPath = ShellFindFilePathEx(CmdName, mExecutableExtensions)) != NULL) { 1774 // 1775 // See if that file has a script file extension 1776 // 1777 if (StrLen(FileWithPath) > 4) { 1778 TempLocation = FileWithPath+StrLen(FileWithPath)-4; 1779 TempLocation2 = mScriptExtension; 1780 if (StringNoCaseCompare((VOID*)(&TempLocation), (VOID*)(&TempLocation2)) == 0) { 1781 SHELL_FREE_NON_NULL(FileWithPath); 1782 return (Script_File_Name); 1783 } 1784 } 1785 1786 // 1787 // Was a file, but not a script. we treat this as an application. 1788 // 1789 SHELL_FREE_NON_NULL(FileWithPath); 1790 return (Efi_Application); 1791 } 1792 1793 SHELL_FREE_NON_NULL(FileWithPath); 1794 // 1795 // No clue what this is... return invalid flag... 1796 // 1797 return (Unknown_Invalid); 1798 } 1799 1800 /** 1801 Determine if the first item in a command line is valid. 1802 1803 @param[in] CmdLine The command line to parse. 1804 1805 @retval EFI_SUCCESS The item is valid. 1806 @retval EFI_OUT_OF_RESOURCES A memory allocation failed. 1807 @retval EFI_NOT_FOUND The operation type is unknown or invalid. 1808 **/ 1809 EFI_STATUS 1810 EFIAPI 1811 IsValidSplit( 1812 IN CONST CHAR16 *CmdLine 1813 ) 1814 { 1815 CHAR16 *Temp; 1816 CHAR16 *FirstParameter; 1817 CHAR16 *TempWalker; 1818 EFI_STATUS Status; 1819 1820 Temp = NULL; 1821 1822 Temp = StrnCatGrow(&Temp, NULL, CmdLine, 0); 1823 if (Temp == NULL) { 1824 return (EFI_OUT_OF_RESOURCES); 1825 } 1826 1827 FirstParameter = StrStr(Temp, L"|"); 1828 if (FirstParameter != NULL) { 1829 *FirstParameter = CHAR_NULL; 1830 } 1831 1832 FirstParameter = NULL; 1833 1834 // 1835 // Process the command line 1836 // 1837 Status = ProcessCommandLineToFinal(&Temp); 1838 1839 if (!EFI_ERROR(Status)) { 1840 FirstParameter = AllocateZeroPool(StrSize(CmdLine)); 1841 if (FirstParameter == NULL) { 1842 SHELL_FREE_NON_NULL(Temp); 1843 return (EFI_OUT_OF_RESOURCES); 1844 } 1845 TempWalker = (CHAR16*)Temp; 1846 if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CmdLine)))) { 1847 if (GetOperationType(FirstParameter) == Unknown_Invalid) { 1848 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter); 1849 SetLastError(SHELL_NOT_FOUND); 1850 Status = EFI_NOT_FOUND; 1851 } 1852 } 1853 } 1854 1855 SHELL_FREE_NON_NULL(Temp); 1856 SHELL_FREE_NON_NULL(FirstParameter); 1857 return Status; 1858 } 1859 1860 /** 1861 Determine if a command line contains with a split contains only valid commands. 1296 1862 1297 1863 @param[in] CmdLine The command line to parse. 1864 1865 @retval EFI_SUCCESS CmdLine has only valid commands, application, or has no split. 1866 @retval EFI_ABORTED CmdLine has at least one invalid command or application. 1867 **/ 1868 EFI_STATUS 1869 EFIAPI 1870 VerifySplit( 1871 IN CONST CHAR16 *CmdLine 1872 ) 1873 { 1874 CONST CHAR16 *TempSpot; 1875 EFI_STATUS Status; 1876 1877 // 1878 // Verify up to the pipe or end character 1879 // 1880 Status = IsValidSplit(CmdLine); 1881 if (EFI_ERROR(Status)) { 1882 return (Status); 1883 } 1884 1885 // 1886 // If this was the only item, then get out 1887 // 1888 if (!ContainsSplit(CmdLine)) { 1889 return (EFI_SUCCESS); 1890 } 1891 1892 // 1893 // recurse to verify the next item 1894 // 1895 TempSpot = FindFirstCharacter(CmdLine, L"|", L'^') + 1; 1896 return (VerifySplit(TempSpot)); 1897 } 1898 1899 /** 1900 Process a split based operation. 1901 1902 @param[in] CmdLine pointer to the command line to process 1903 1904 @retval EFI_SUCCESS The operation was successful 1905 @return an error occured. 1906 **/ 1907 EFI_STATUS 1908 EFIAPI 1909 ProcessNewSplitCommandLine( 1910 IN CONST CHAR16 *CmdLine 1911 ) 1912 { 1913 SPLIT_LIST *Split; 1914 EFI_STATUS Status; 1915 1916 Status = VerifySplit(CmdLine); 1917 if (EFI_ERROR(Status)) { 1918 return (Status); 1919 } 1920 1921 Split = NULL; 1922 1923 // 1924 // are we in an existing split??? 1925 // 1926 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) { 1927 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link); 1928 } 1929 1930 if (Split == NULL) { 1931 Status = RunSplitCommand(CmdLine, NULL, NULL); 1932 } else { 1933 Status = RunSplitCommand(CmdLine, Split->SplitStdIn, Split->SplitStdOut); 1934 } 1935 if (EFI_ERROR(Status)) { 1936 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_SPLIT), ShellInfoObject.HiiHandle, CmdLine); 1937 } 1938 return (Status); 1939 } 1940 1941 /** 1942 Handle a request to change the current file system. 1943 1944 @param[in] CmdLine The passed in command line. 1945 1946 @retval EFI_SUCCESS The operation was successful. 1947 **/ 1948 EFI_STATUS 1949 EFIAPI 1950 ChangeMappedDrive( 1951 IN CONST CHAR16 *CmdLine 1952 ) 1953 { 1954 EFI_STATUS Status; 1955 Status = EFI_SUCCESS; 1956 1957 // 1958 // make sure we are the right operation 1959 // 1960 ASSERT(CmdLine[(StrLen(CmdLine)-1)] == L':' && StrStr(CmdLine, L" ") == NULL); 1961 1962 // 1963 // Call the protocol API to do the work 1964 // 1965 Status = ShellInfoObject.NewEfiShellProtocol->SetCurDir(NULL, CmdLine); 1966 1967 // 1968 // Report any errors 1969 // 1970 if (EFI_ERROR(Status)) { 1971 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_MAPPING), ShellInfoObject.HiiHandle, CmdLine); 1972 } 1973 1974 return (Status); 1975 } 1976 1977 /** 1978 Reprocess the command line to direct all -? to the help command. 1979 1980 if found, will add "help" as argv[0], and move the rest later. 1981 1982 @param[in,out] CmdLine pointer to the command line to update 1983 **/ 1984 EFI_STATUS 1985 EFIAPI 1986 DoHelpUpdate( 1987 IN OUT CHAR16 **CmdLine 1988 ) 1989 { 1990 CHAR16 *CurrentParameter; 1991 CHAR16 *Walker; 1992 CHAR16 *LastWalker; 1993 CHAR16 *NewCommandLine; 1994 EFI_STATUS Status; 1995 1996 Status = EFI_SUCCESS; 1997 1998 CurrentParameter = AllocateZeroPool(StrSize(*CmdLine)); 1999 if (CurrentParameter == NULL) { 2000 return (EFI_OUT_OF_RESOURCES); 2001 } 2002 2003 Walker = *CmdLine; 2004 while(Walker != NULL && *Walker != CHAR_NULL) { 2005 LastWalker = Walker; 2006 if (!EFI_ERROR(GetNextParameter(&Walker, &CurrentParameter, StrSize(*CmdLine)))) { 2007 if (StrStr(CurrentParameter, L"-?") == CurrentParameter) { 2008 LastWalker[0] = L' '; 2009 LastWalker[1] = L' '; 2010 NewCommandLine = AllocateZeroPool(StrSize(L"help ") + StrSize(*CmdLine)); 2011 if (NewCommandLine == NULL) { 2012 Status = EFI_OUT_OF_RESOURCES; 2013 break; 2014 } 2015 2016 // 2017 // We know the space is sufficient since we just calculated it. 2018 // 2019 StrnCpy(NewCommandLine, L"help ", 5); 2020 StrnCat(NewCommandLine, *CmdLine, StrLen(*CmdLine)); 2021 SHELL_FREE_NON_NULL(*CmdLine); 2022 *CmdLine = NewCommandLine; 2023 break; 2024 } 2025 } 2026 } 2027 2028 SHELL_FREE_NON_NULL(CurrentParameter); 2029 2030 return (Status); 2031 } 2032 2033 /** 2034 Function to update the shell variable "lasterror". 2035 2036 @param[in] ErrorCode the error code to put into lasterror. 2037 **/ 2038 EFI_STATUS 2039 EFIAPI 2040 SetLastError( 2041 IN CONST SHELL_STATUS ErrorCode 2042 ) 2043 { 2044 CHAR16 LeString[19]; 2045 if (sizeof(EFI_STATUS) == sizeof(UINT64)) { 2046 UnicodeSPrint(LeString, sizeof(LeString), L"0x%Lx", ErrorCode); 2047 } else { 2048 UnicodeSPrint(LeString, sizeof(LeString), L"0x%x", ErrorCode); 2049 } 2050 DEBUG_CODE(InternalEfiShellSetEnv(L"debuglasterror", LeString, TRUE);); 2051 InternalEfiShellSetEnv(L"lasterror", LeString, TRUE); 2052 2053 return (EFI_SUCCESS); 2054 } 2055 2056 /** 2057 Converts the command line to it's post-processed form. this replaces variables and alias' per UEFI Shell spec. 2058 2059 @param[in,out] CmdLine pointer to the command line to update 2060 2061 @retval EFI_SUCCESS The operation was successful 2062 @retval EFI_OUT_OF_RESOURCES A memory allocation failed. 2063 @return some other error occured 2064 **/ 2065 EFI_STATUS 2066 EFIAPI 2067 ProcessCommandLineToFinal( 2068 IN OUT CHAR16 **CmdLine 2069 ) 2070 { 2071 EFI_STATUS Status; 2072 TrimSpaces(CmdLine); 2073 2074 Status = ShellSubstituteAliases(CmdLine); 2075 if (EFI_ERROR(Status)) { 2076 return (Status); 2077 } 2078 2079 TrimSpaces(CmdLine); 2080 2081 Status = ShellSubstituteVariables(CmdLine); 2082 if (EFI_ERROR(Status)) { 2083 return (Status); 2084 } 2085 ASSERT (*CmdLine != NULL); 2086 2087 TrimSpaces(CmdLine); 2088 2089 // 2090 // update for help parsing 2091 // 2092 if (StrStr(*CmdLine, L"?") != NULL) { 2093 // 2094 // This may do nothing if the ? does not indicate help. 2095 // Save all the details for in the API below. 2096 // 2097 Status = DoHelpUpdate(CmdLine); 2098 } 2099 2100 TrimSpaces(CmdLine); 2101 2102 return (EFI_SUCCESS); 2103 } 2104 2105 /** 2106 Run an internal shell command. 2107 2108 This API will upadate the shell's environment since these commands are libraries. 2109 2110 @param[in] CmdLine the command line to run. 2111 @param[in] FirstParameter the first parameter on the command line 2112 @param[in] ParamProtocol the shell parameters protocol pointer 1298 2113 1299 2114 @retval EFI_SUCCESS The command was completed. … … 1302 2117 EFI_STATUS 1303 2118 EFIAPI 1304 RunCommand( 1305 IN CONST CHAR16 *CmdLine 1306 ) 2119 RunInternalCommand( 2120 IN CONST CHAR16 *CmdLine, 2121 IN CHAR16 *FirstParameter, 2122 IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol 2123 ) 1307 2124 { 1308 2125 EFI_STATUS Status; 1309 CHAR16 *CommandName;1310 SHELL_STATUS ShellStatus;1311 2126 UINTN Argc; 1312 2127 CHAR16 **Argv; 2128 SHELL_STATUS CommandReturnedStatus; 1313 2129 BOOLEAN LastError; 1314 CHAR16 LeString[11]; 1315 CHAR16 *PostAliasCmdLine; 1316 UINTN PostAliasSize; 1317 CHAR16 *PostVariableCmdLine; 2130 CHAR16 *Walker; 2131 CHAR16 *NewCmdLine; 2132 2133 NewCmdLine = AllocateCopyPool (StrSize (CmdLine), CmdLine); 2134 if (NewCmdLine == NULL) { 2135 return EFI_OUT_OF_RESOURCES; 2136 } 2137 2138 for (Walker = NewCmdLine; Walker != NULL && *Walker != CHAR_NULL ; Walker++) { 2139 if (*Walker == L'^' && *(Walker+1) == L'#') { 2140 CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0])); 2141 } 2142 } 2143 2144 // 2145 // get the argc and argv updated for internal commands 2146 // 2147 Status = UpdateArgcArgv(ParamProtocol, NewCmdLine, &Argv, &Argc); 2148 if (!EFI_ERROR(Status)) { 2149 // 2150 // Run the internal command. 2151 // 2152 Status = ShellCommandRunCommandHandler(FirstParameter, &CommandReturnedStatus, &LastError); 2153 2154 if (!EFI_ERROR(Status)) { 2155 // 2156 // Update last error status. 2157 // some commands do not update last error. 2158 // 2159 if (LastError) { 2160 SetLastError(CommandReturnedStatus); 2161 } 2162 2163 // 2164 // Pass thru the exitcode from the app. 2165 // 2166 if (ShellCommandGetExit()) { 2167 // 2168 // An Exit was requested ("exit" command), pass its value up. 2169 // 2170 Status = CommandReturnedStatus; 2171 } else if (CommandReturnedStatus != SHELL_SUCCESS && IsScriptOnlyCommand(FirstParameter)) { 2172 // 2173 // Always abort when a script only command fails for any reason 2174 // 2175 Status = EFI_ABORTED; 2176 } else if (ShellCommandGetCurrentScriptFile() != NULL && CommandReturnedStatus == SHELL_ABORTED) { 2177 // 2178 // Abort when in a script and a command aborted 2179 // 2180 Status = EFI_ABORTED; 2181 } 2182 } 2183 } 2184 2185 // 2186 // This is guarenteed to be called after UpdateArgcArgv no matter what else happened. 2187 // This is safe even if the update API failed. In this case, it may be a no-op. 2188 // 2189 RestoreArgcArgv(ParamProtocol, &Argv, &Argc); 2190 2191 // 2192 // If a script is running and the command is not a scipt only command, then 2193 // change return value to success so the script won't halt (unless aborted). 2194 // 2195 // Script only commands have to be able halt the script since the script will 2196 // not operate if they are failing. 2197 // 2198 if ( ShellCommandGetCurrentScriptFile() != NULL 2199 && !IsScriptOnlyCommand(FirstParameter) 2200 && Status != EFI_ABORTED 2201 ) { 2202 Status = EFI_SUCCESS; 2203 } 2204 2205 FreePool (NewCmdLine); 2206 return (Status); 2207 } 2208 2209 /** 2210 Function to run the command or file. 2211 2212 @param[in] Type the type of operation being run. 2213 @param[in] CmdLine the command line to run. 2214 @param[in] FirstParameter the first parameter on the command line 2215 @param[in] ParamProtocol the shell parameters protocol pointer 2216 2217 @retval EFI_SUCCESS The command was completed. 2218 @retval EFI_ABORTED The command's operation was aborted. 2219 **/ 2220 EFI_STATUS 2221 EFIAPI 2222 RunCommandOrFile( 2223 IN SHELL_OPERATION_TYPES Type, 2224 IN CONST CHAR16 *CmdLine, 2225 IN CHAR16 *FirstParameter, 2226 IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol 2227 ) 2228 { 2229 EFI_STATUS Status; 2230 EFI_STATUS StartStatus; 1318 2231 CHAR16 *CommandWithPath; 1319 CONST EFI_DEVICE_PATH_PROTOCOL *DevPath; 1320 CONST CHAR16 *TempLocation; 1321 CONST CHAR16 *TempLocation2; 2232 EFI_DEVICE_PATH_PROTOCOL *DevPath; 2233 SHELL_STATUS CalleeExitStatus; 2234 2235 Status = EFI_SUCCESS; 2236 CommandWithPath = NULL; 2237 DevPath = NULL; 2238 CalleeExitStatus = SHELL_INVALID_PARAMETER; 2239 2240 switch (Type) { 2241 case Internal_Command: 2242 Status = RunInternalCommand(CmdLine, FirstParameter, ParamProtocol); 2243 break; 2244 case Script_File_Name: 2245 case Efi_Application: 2246 // 2247 // Process a fully qualified path 2248 // 2249 if (StrStr(FirstParameter, L":") != NULL) { 2250 ASSERT (CommandWithPath == NULL); 2251 if (ShellIsFile(FirstParameter) == EFI_SUCCESS) { 2252 CommandWithPath = StrnCatGrow(&CommandWithPath, NULL, FirstParameter, 0); 2253 } 2254 } 2255 2256 // 2257 // Process a relative path and also check in the path environment variable 2258 // 2259 if (CommandWithPath == NULL) { 2260 CommandWithPath = ShellFindFilePathEx(FirstParameter, mExecutableExtensions); 2261 } 2262 2263 // 2264 // This should be impossible now. 2265 // 2266 ASSERT(CommandWithPath != NULL); 2267 2268 // 2269 // Make sure that path is not just a directory (or not found) 2270 // 2271 if (!EFI_ERROR(ShellIsDirectory(CommandWithPath))) { 2272 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter); 2273 SetLastError(SHELL_NOT_FOUND); 2274 } 2275 switch (Type) { 2276 case Script_File_Name: 2277 Status = RunScriptFile (CommandWithPath, NULL, CmdLine, ParamProtocol); 2278 break; 2279 case Efi_Application: 2280 // 2281 // Get the device path of the application image 2282 // 2283 DevPath = ShellInfoObject.NewEfiShellProtocol->GetDevicePathFromFilePath(CommandWithPath); 2284 if (DevPath == NULL){ 2285 Status = EFI_OUT_OF_RESOURCES; 2286 break; 2287 } 2288 2289 // 2290 // Execute the device path 2291 // 2292 Status = InternalShellExecuteDevicePath( 2293 &gImageHandle, 2294 DevPath, 2295 CmdLine, 2296 NULL, 2297 &StartStatus 2298 ); 2299 2300 SHELL_FREE_NON_NULL(DevPath); 2301 2302 if(EFI_ERROR (Status)) { 2303 CalleeExitStatus = (SHELL_STATUS) (Status & (~MAX_BIT)); 2304 } else { 2305 CalleeExitStatus = (SHELL_STATUS) StartStatus; 2306 } 2307 2308 // 2309 // Update last error status. 2310 // 2311 // Status is an EFI_STATUS. Clear top bit to convert to SHELL_STATUS 2312 SetLastError(CalleeExitStatus); 2313 break; 2314 default: 2315 // 2316 // Do nothing. 2317 // 2318 break; 2319 } 2320 break; 2321 default: 2322 // 2323 // Do nothing. 2324 // 2325 break; 2326 } 2327 2328 SHELL_FREE_NON_NULL(CommandWithPath); 2329 2330 return (Status); 2331 } 2332 2333 /** 2334 Function to setup StdIn, StdErr, StdOut, and then run the command or file. 2335 2336 @param[in] Type the type of operation being run. 2337 @param[in] CmdLine the command line to run. 2338 @param[in] FirstParameter the first parameter on the command line. 2339 @param[in] ParamProtocol the shell parameters protocol pointer 2340 2341 @retval EFI_SUCCESS The command was completed. 2342 @retval EFI_ABORTED The command's operation was aborted. 2343 **/ 2344 EFI_STATUS 2345 EFIAPI 2346 SetupAndRunCommandOrFile( 2347 IN SHELL_OPERATION_TYPES Type, 2348 IN CHAR16 *CmdLine, 2349 IN CHAR16 *FirstParameter, 2350 IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol 2351 ) 2352 { 2353 EFI_STATUS Status; 1322 2354 SHELL_FILE_HANDLE OriginalStdIn; 1323 2355 SHELL_FILE_HANDLE OriginalStdOut; 1324 2356 SHELL_FILE_HANDLE OriginalStdErr; 1325 2357 SYSTEM_TABLE_INFO OriginalSystemTableInfo; 1326 CHAR16 *TempLocation3; 1327 UINTN Count; 1328 UINTN Count2; 2358 2359 // 2360 // Update the StdIn, StdOut, and StdErr for redirection to environment variables, files, etc... unicode and ASCII 2361 // 2362 Status = UpdateStdInStdOutStdErr(ParamProtocol, CmdLine, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr, &OriginalSystemTableInfo); 2363 2364 // 2365 // The StdIn, StdOut, and StdErr are set up. 2366 // Now run the command, script, or application 2367 // 2368 if (!EFI_ERROR(Status)) { 2369 TrimSpaces(&CmdLine); 2370 Status = RunCommandOrFile(Type, CmdLine, FirstParameter, ParamProtocol); 2371 } 2372 2373 // 2374 // Now print errors 2375 // 2376 if (EFI_ERROR(Status)) { 2377 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_ERROR), ShellInfoObject.HiiHandle, (VOID*)(Status)); 2378 } 2379 2380 // 2381 // put back the original StdIn, StdOut, and StdErr 2382 // 2383 RestoreStdInStdOutStdErr(ParamProtocol, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr, &OriginalSystemTableInfo); 2384 2385 return (Status); 2386 } 2387 2388 /** 2389 Function will process and run a command line. 2390 2391 This will determine if the command line represents an internal shell 2392 command or dispatch an external application. 2393 2394 @param[in] CmdLine The command line to parse. 2395 2396 @retval EFI_SUCCESS The command was completed. 2397 @retval EFI_ABORTED The command's operation was aborted. 2398 **/ 2399 EFI_STATUS 2400 EFIAPI 2401 RunCommand( 2402 IN CONST CHAR16 *CmdLine 2403 ) 2404 { 2405 EFI_STATUS Status; 1329 2406 CHAR16 *CleanOriginal; 1330 SPLIT_LIST *Split; 2407 CHAR16 *FirstParameter; 2408 CHAR16 *TempWalker; 2409 SHELL_OPERATION_TYPES Type; 1331 2410 1332 2411 ASSERT(CmdLine != NULL); … … 1335 2414 } 1336 2415 1337 CommandName = NULL;1338 PostVariableCmdLine = NULL;1339 PostAliasCmdLine = NULL;1340 CommandWithPath = NULL;1341 DevPath = NULL;1342 2416 Status = EFI_SUCCESS; 1343 2417 CleanOriginal = NULL; 1344 Split = NULL;1345 2418 1346 2419 CleanOriginal = StrnCatGrow(&CleanOriginal, NULL, CmdLine, 0); … … 1348 2421 return (EFI_OUT_OF_RESOURCES); 1349 2422 } 1350 while (CleanOriginal[StrLen(CleanOriginal)-1] == L' ') { 1351 CleanOriginal[StrLen(CleanOriginal)-1] = CHAR_NULL; 1352 } 1353 while (CleanOriginal[0] == L' ') { 1354 CopyMem(CleanOriginal, CleanOriginal+1, StrSize(CleanOriginal) - sizeof(CleanOriginal[0])); 1355 } 1356 1357 CommandName = NULL; 1358 if (StrStr(CleanOriginal, L" ") == NULL){ 1359 StrnCatGrow(&CommandName, NULL, CleanOriginal, 0); 2423 2424 TrimSpaces(&CleanOriginal); 2425 2426 // 2427 // NULL out comments (leveraged from RunScriptFileHandle() ). 2428 // The # character on a line is used to denote that all characters on the same line 2429 // and to the right of the # are to be ignored by the shell. 2430 // Afterward, again remove spaces, in case any were between the last command-parameter and '#'. 2431 // 2432 for (TempWalker = CleanOriginal; TempWalker != NULL && *TempWalker != CHAR_NULL; TempWalker++) { 2433 if (*TempWalker == L'^') { 2434 if (*(TempWalker + 1) == L'#') { 2435 TempWalker++; 2436 } 2437 } else if (*TempWalker == L'#') { 2438 *TempWalker = CHAR_NULL; 2439 } 2440 } 2441 2442 TrimSpaces(&CleanOriginal); 2443 2444 // 2445 // Handle case that passed in command line is just 1 or more " " characters. 2446 // 2447 if (StrLen (CleanOriginal) == 0) { 2448 SHELL_FREE_NON_NULL(CleanOriginal); 2449 return (EFI_SUCCESS); 2450 } 2451 2452 Status = ProcessCommandLineToFinal(&CleanOriginal); 2453 if (EFI_ERROR(Status)) { 2454 SHELL_FREE_NON_NULL(CleanOriginal); 2455 return (Status); 2456 } 2457 2458 // 2459 // We dont do normal processing with a split command line (output from one command input to another) 2460 // 2461 if (ContainsSplit(CleanOriginal)) { 2462 Status = ProcessNewSplitCommandLine(CleanOriginal); 2463 SHELL_FREE_NON_NULL(CleanOriginal); 2464 return (Status); 2465 } 2466 2467 // 2468 // We need the first parameter information so we can determine the operation type 2469 // 2470 FirstParameter = AllocateZeroPool(StrSize(CleanOriginal)); 2471 if (FirstParameter == NULL) { 2472 SHELL_FREE_NON_NULL(CleanOriginal); 2473 return (EFI_OUT_OF_RESOURCES); 2474 } 2475 TempWalker = CleanOriginal; 2476 if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CleanOriginal)))) { 2477 // 2478 // Depending on the first parameter we change the behavior 2479 // 2480 switch (Type = GetOperationType(FirstParameter)) { 2481 case File_Sys_Change: 2482 Status = ChangeMappedDrive (FirstParameter); 2483 break; 2484 case Internal_Command: 2485 case Script_File_Name: 2486 case Efi_Application: 2487 Status = SetupAndRunCommandOrFile(Type, CleanOriginal, FirstParameter, ShellInfoObject.NewShellParametersProtocol); 2488 break; 2489 default: 2490 // 2491 // Whatever was typed, it was invalid. 2492 // 2493 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter); 2494 SetLastError(SHELL_NOT_FOUND); 2495 break; 2496 } 1360 2497 } else { 1361 StrnCatGrow(&CommandName, NULL, CleanOriginal, StrStr(CleanOriginal, L" ") - CleanOriginal); 1362 } 1363 1364 ASSERT(PostAliasCmdLine == NULL); 1365 if (!ShellCommandIsCommandOnList(CommandName)) { 1366 // 1367 // Convert via alias 1368 // 1369 Status = ShellConvertAlias(&CommandName); 1370 PostAliasSize = 0; 1371 PostAliasCmdLine = StrnCatGrow(&PostAliasCmdLine, &PostAliasSize, CommandName, 0); 1372 PostAliasCmdLine = StrnCatGrow(&PostAliasCmdLine, &PostAliasSize, StrStr(CleanOriginal, L" "), 0); 1373 ASSERT_EFI_ERROR(Status); 1374 } else { 1375 PostAliasCmdLine = StrnCatGrow(&PostAliasCmdLine, NULL, CleanOriginal, 0); 1376 } 1377 1378 if (CleanOriginal != NULL) { 1379 FreePool(CleanOriginal); 1380 CleanOriginal = NULL; 1381 } 1382 1383 if (CommandName != NULL) { 1384 FreePool(CommandName); 1385 CommandName = NULL; 1386 } 1387 1388 PostVariableCmdLine = ShellConvertVariables(PostAliasCmdLine); 1389 1390 // 1391 // we can now free the modified by alias command line 1392 // 1393 if (PostAliasCmdLine != NULL) { 1394 FreePool(PostAliasCmdLine); 1395 PostAliasCmdLine = NULL; 1396 } 1397 1398 if (PostVariableCmdLine == NULL) { 1399 return (EFI_OUT_OF_RESOURCES); 1400 } 1401 1402 while (PostVariableCmdLine[StrLen(PostVariableCmdLine)-1] == L' ') { 1403 PostVariableCmdLine[StrLen(PostVariableCmdLine)-1] = CHAR_NULL; 1404 } 1405 while (PostVariableCmdLine[0] == L' ') { 1406 CopyMem(PostVariableCmdLine, PostVariableCmdLine+1, StrSize(PostVariableCmdLine) - sizeof(PostVariableCmdLine[0])); 1407 } 1408 1409 // 1410 // We dont do normal processing with a split command line (output from one command input to another) 1411 // 1412 TempLocation3 = NULL; 1413 if (StrStr(PostVariableCmdLine, L"|") != NULL) { 1414 for (TempLocation3 = PostVariableCmdLine ; TempLocation3 != NULL && *TempLocation3 != CHAR_NULL ; TempLocation3++) { 1415 if (*TempLocation3 == L'^' && *(TempLocation3+1) == L'|') { 1416 TempLocation3++; 1417 } else if (*TempLocation3 == L'|') { 1418 break; 1419 } 1420 } 1421 } 1422 if (TempLocation3 != NULL && *TempLocation3 != CHAR_NULL) { 1423 // 1424 // are we in an existing split??? 1425 // 1426 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) { 1427 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link); 1428 } 1429 1430 if (Split == NULL) { 1431 Status = RunSplitCommand(PostVariableCmdLine, NULL, NULL); 1432 } else { 1433 Status = RunSplitCommand(PostVariableCmdLine, Split->SplitStdIn, Split->SplitStdOut); 1434 } 1435 } else { 1436 1437 // 1438 // If this is a mapped drive change handle that... 1439 // 1440 if (PostVariableCmdLine[(StrLen(PostVariableCmdLine)-1)] == L':' && StrStr(PostVariableCmdLine, L" ") == NULL) { 1441 Status = ShellInfoObject.NewEfiShellProtocol->SetCurDir(NULL, PostVariableCmdLine); 1442 if (EFI_ERROR(Status)) { 1443 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_MAPPING), ShellInfoObject.HiiHandle, PostVariableCmdLine); 1444 } 1445 FreePool(PostVariableCmdLine); 1446 return (Status); 1447 } 1448 1449 ///@todo update this section to divide into 3 ways - run internal command, run split (above), and run an external file... 1450 /// We waste a lot of time doing processing like StdIn,StdOut,Argv,Argc for things that are external files... 1451 1452 1453 1454 Status = UpdateStdInStdOutStdErr(ShellInfoObject.NewShellParametersProtocol, PostVariableCmdLine, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr, &OriginalSystemTableInfo); 1455 if (EFI_ERROR(Status)) { 1456 if (Status == EFI_NOT_FOUND) { 1457 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_REDUNDA_REDIR), ShellInfoObject.HiiHandle); 1458 } else { 1459 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_REDIR), ShellInfoObject.HiiHandle); 1460 } 1461 } else { 1462 while (PostVariableCmdLine[StrLen(PostVariableCmdLine)-1] == L' ') { 1463 PostVariableCmdLine[StrLen(PostVariableCmdLine)-1] = CHAR_NULL; 1464 } 1465 while (PostVariableCmdLine[0] == L' ') { 1466 CopyMem(PostVariableCmdLine, PostVariableCmdLine+1, StrSize(PostVariableCmdLine) - sizeof(PostVariableCmdLine[0])); 1467 } 1468 1469 // 1470 // get the argc and argv updated for internal commands 1471 // 1472 Status = UpdateArgcArgv(ShellInfoObject.NewShellParametersProtocol, PostVariableCmdLine, &Argv, &Argc); 1473 ASSERT_EFI_ERROR(Status); 1474 1475 for (Count = 0 ; Count < ShellInfoObject.NewShellParametersProtocol->Argc ; Count++) { 1476 if (StrStr(ShellInfoObject.NewShellParametersProtocol->Argv[Count], L"-?") == ShellInfoObject.NewShellParametersProtocol->Argv[Count] 1477 || (ShellInfoObject.NewShellParametersProtocol->Argv[0][0] == L'?' && ShellInfoObject.NewShellParametersProtocol->Argv[0][1] == CHAR_NULL) 1478 ) { 1479 // 1480 // We need to redo the arguments since a parameter was -? 1481 // move them all down 1 to the end, then up one then replace the first with help 1482 // 1483 FreePool(ShellInfoObject.NewShellParametersProtocol->Argv[Count]); 1484 ShellInfoObject.NewShellParametersProtocol->Argv[Count] = NULL; 1485 for (Count2 = Count ; (Count2 + 1) < ShellInfoObject.NewShellParametersProtocol->Argc ; Count2++) { 1486 ShellInfoObject.NewShellParametersProtocol->Argv[Count2] = ShellInfoObject.NewShellParametersProtocol->Argv[Count2+1]; 1487 } 1488 ShellInfoObject.NewShellParametersProtocol->Argv[Count2] = NULL; 1489 for (Count2 = ShellInfoObject.NewShellParametersProtocol->Argc -1 ; Count2 > 0 ; Count2--) { 1490 ShellInfoObject.NewShellParametersProtocol->Argv[Count2] = ShellInfoObject.NewShellParametersProtocol->Argv[Count2-1]; 1491 } 1492 ShellInfoObject.NewShellParametersProtocol->Argv[0] = NULL; 1493 ShellInfoObject.NewShellParametersProtocol->Argv[0] = StrnCatGrow(&ShellInfoObject.NewShellParametersProtocol->Argv[0], NULL, L"help", 0); 1494 break; 1495 } 1496 } 1497 1498 // 1499 // command or file? 1500 // 1501 if (ShellCommandIsCommandOnList(ShellInfoObject.NewShellParametersProtocol->Argv[0])) { 1502 // 1503 // Run the command (which was converted if it was an alias) 1504 // 1505 if (!EFI_ERROR(Status)) { 1506 Status = ShellCommandRunCommandHandler(ShellInfoObject.NewShellParametersProtocol->Argv[0], &ShellStatus, &LastError); 1507 ASSERT_EFI_ERROR(Status); 1508 UnicodeSPrint(LeString, sizeof(LeString)*sizeof(LeString[0]), L"0x%08x", ShellStatus); 1509 DEBUG_CODE(InternalEfiShellSetEnv(L"DebugLasterror", LeString, TRUE);); 1510 if (LastError) { 1511 InternalEfiShellSetEnv(L"Lasterror", LeString, TRUE); 1512 } 1513 // 1514 // Pass thru the exitcode from the app. 1515 // 1516 if (ShellCommandGetExit()) { 1517 Status = ShellStatus; 1518 } else if (ShellStatus != 0 && IsScriptOnlyCommand(ShellInfoObject.NewShellParametersProtocol->Argv[0])) { 1519 Status = EFI_ABORTED; 1520 } 1521 } 1522 } else { 1523 // 1524 // run an external file (or script) 1525 // 1526 if (StrStr(ShellInfoObject.NewShellParametersProtocol->Argv[0], L":") != NULL) { 1527 ASSERT (CommandWithPath == NULL); 1528 if (ShellIsFile(ShellInfoObject.NewShellParametersProtocol->Argv[0]) == EFI_SUCCESS) { 1529 CommandWithPath = StrnCatGrow(&CommandWithPath, NULL, ShellInfoObject.NewShellParametersProtocol->Argv[0], 0); 1530 } 1531 } 1532 if (CommandWithPath == NULL) { 1533 CommandWithPath = ShellFindFilePathEx(ShellInfoObject.NewShellParametersProtocol->Argv[0], mExecutableExtensions); 1534 } 1535 if (CommandWithPath == NULL || ShellIsDirectory(CommandWithPath) == EFI_SUCCESS) { 1536 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, ShellInfoObject.NewShellParametersProtocol->Argv[0]); 1537 } else { 1538 // 1539 // Check if it's a NSH (script) file. 1540 // 1541 TempLocation = CommandWithPath+StrLen(CommandWithPath)-4; 1542 TempLocation2 = mScriptExtension; 1543 if ((StrLen(CommandWithPath) > 4) && (StringNoCaseCompare((VOID*)(&TempLocation), (VOID*)(&TempLocation2)) == 0)) { 1544 Status = RunScriptFile (CommandWithPath); 1545 } else { 1546 DevPath = ShellInfoObject.NewEfiShellProtocol->GetDevicePathFromFilePath(CommandWithPath); 1547 ASSERT(DevPath != NULL); 1548 Status = InternalShellExecuteDevicePath( 1549 &gImageHandle, 1550 DevPath, 1551 PostVariableCmdLine, 1552 NULL, 1553 NULL 1554 ); 1555 } 1556 } 1557 } 1558 CommandName = StrnCatGrow(&CommandName, NULL, ShellInfoObject.NewShellParametersProtocol->Argv[0], 0); 1559 1560 RestoreArgcArgv(ShellInfoObject.NewShellParametersProtocol, &Argv, &Argc); 1561 1562 RestoreStdInStdOutStdErr(ShellInfoObject.NewShellParametersProtocol, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr, &OriginalSystemTableInfo); 1563 } 1564 if (CommandName != NULL) { 1565 if (ShellCommandGetCurrentScriptFile() != NULL && !IsScriptOnlyCommand(CommandName)) { 1566 // 1567 // if this is NOT a scipt only command return success so the script won't quit. 1568 // prevent killing the script - this is the only place where we know the actual command name (after alias and variable replacement...) 1569 // 1570 Status = EFI_SUCCESS; 1571 } 1572 } 1573 } 1574 1575 SHELL_FREE_NON_NULL(CommandName); 1576 SHELL_FREE_NON_NULL(CommandWithPath); 1577 SHELL_FREE_NON_NULL(PostVariableCmdLine); 2498 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter); 2499 SetLastError(SHELL_NOT_FOUND); 2500 } 2501 2502 SHELL_FREE_NON_NULL(CleanOriginal); 2503 SHELL_FREE_NON_NULL(FirstParameter); 1578 2504 1579 2505 return (Status); … … 1692 2618 CommandLine = ShellFileHandleReturnLine(Handle, &Ascii); 1693 2619 LineCount++; 1694 if (CommandLine == NULL || StrLen(CommandLine) == 0) { 2620 if (CommandLine == NULL || StrLen(CommandLine) == 0 || CommandLine[0] == '#') { 2621 SHELL_FREE_NON_NULL(CommandLine); 1695 2622 continue; 1696 2623 } 1697 2624 NewScriptFile->CurrentCommand = AllocateZeroPool(sizeof(SCRIPT_COMMAND_LIST)); 1698 2625 if (NewScriptFile->CurrentCommand == NULL) { 2626 SHELL_FREE_NON_NULL(CommandLine); 1699 2627 DeleteScriptFileStruct(NewScriptFile); 1700 2628 return (EFI_OUT_OF_RESOURCES); … … 1733 2661 ){ 1734 2662 ASSERT(CommandLine2 != NULL); 1735 Str Cpy(CommandLine2, NewScriptFile->CurrentCommand->Cl);2663 StrnCpy(CommandLine2, NewScriptFile->CurrentCommand->Cl, PcdGet16(PcdShellPrintBufferSize)/sizeof(CHAR16)-1); 1736 2664 1737 2665 // … … 1740 2668 for (CommandLine3 = CommandLine2 ; CommandLine3 != NULL && *CommandLine3 != CHAR_NULL ; CommandLine3++) { 1741 2669 if (*CommandLine3 == L'^') { 1742 if ( *(CommandLine3+1) == L'#' ||*(CommandLine3+1) == L':') {2670 if ( *(CommandLine3+1) == L':') { 1743 2671 CopyMem(CommandLine3, CommandLine3+1, StrSize(CommandLine3) - sizeof(CommandLine3[0])); 2672 } else if (*(CommandLine3+1) == L'#') { 2673 CommandLine3++; 1744 2674 } 1745 2675 } else if (*CommandLine3 == L'#') { … … 1752 2682 // Due to variability in starting the find and replace action we need to have both buffers the same. 1753 2683 // 1754 Str Cpy(CommandLine, CommandLine2);2684 StrnCpy(CommandLine, CommandLine2, PcdGet16(PcdShellPrintBufferSize)/sizeof(CHAR16)-1); 1755 2685 1756 2686 // … … 1804 2734 Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%9", L"\"\"", FALSE, FALSE); 1805 2735 1806 Str Cpy(CommandLine2, CommandLine);2736 StrnCpy(CommandLine2, CommandLine, PcdGet16(PcdShellPrintBufferSize)/sizeof(CHAR16)-1); 1807 2737 1808 2738 LastCommand = NewScriptFile->CurrentCommand; … … 1826 2756 1827 2757 // 1828 // Now restore the pre-'@' echo state.2758 // If command was "@echo -off" or "@echo -on" then don't restore echo state 1829 2759 // 1830 ShellCommandSetEchoState(PreCommandEchoState); 2760 if (StrCmp (L"@echo -off", CommandLine3) != 0 && 2761 StrCmp (L"@echo -on", CommandLine3) != 0) { 2762 // 2763 // Now restore the pre-'@' echo state. 2764 // 2765 ShellCommandSetEchoState(PreCommandEchoState); 2766 } 1831 2767 } else { 1832 2768 if (ShellCommandGetEchoState()) { … … 1844 2780 1845 2781 if (ShellCommandGetScriptExit()) { 1846 UnicodeSPrint(LeString, sizeof(LeString)*sizeof(LeString[0]), L"0x%Lx", ShellCommandGetExitCode()); 1847 DEBUG_CODE(InternalEfiShellSetEnv(L"DebugLasterror", LeString, TRUE);); 1848 InternalEfiShellSetEnv(L"Lasterror", LeString, TRUE); 2782 // 2783 // ShellCommandGetExitCode() always returns a UINT64 2784 // 2785 UnicodeSPrint(LeString, sizeof(LeString), L"0x%Lx", ShellCommandGetExitCode()); 2786 DEBUG_CODE(InternalEfiShellSetEnv(L"debuglasterror", LeString, TRUE);); 2787 InternalEfiShellSetEnv(L"lasterror", LeString, TRUE); 1849 2788 1850 2789 ShellCommandRegisterExit(FALSE, 0); 1851 2790 Status = EFI_SUCCESS; 2791 break; 2792 } 2793 if (ShellGetExecutionBreakFlag()) { 1852 2794 break; 1853 2795 } … … 1894 2836 1895 2837 @param[in] ScriptPath Pointer to the script file name (including file system path). 2838 @param[in] Handle the handle of the script file already opened. 2839 @param[in] CmdLine the command line to run. 2840 @param[in] ParamProtocol the shell parameters protocol pointer 1896 2841 1897 2842 @retval EFI_SUCCESS the script completed sucessfully … … 1900 2845 EFIAPI 1901 2846 RunScriptFile ( 1902 IN CONST CHAR16 *ScriptPath 2847 IN CONST CHAR16 *ScriptPath, 2848 IN SHELL_FILE_HANDLE Handle OPTIONAL, 2849 IN CONST CHAR16 *CmdLine, 2850 IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol 1903 2851 ) 1904 2852 { 1905 2853 EFI_STATUS Status; 1906 2854 SHELL_FILE_HANDLE FileHandle; 2855 UINTN Argc; 2856 CHAR16 **Argv; 1907 2857 1908 2858 if (ShellIsFile(ScriptPath) != EFI_SUCCESS) { … … 1910 2860 } 1911 2861 1912 Status = ShellOpenFileByName(ScriptPath, &FileHandle, EFI_FILE_MODE_READ, 0); 1913 if (EFI_ERROR(Status)) { 1914 return (Status); 1915 } 1916 1917 Status = RunScriptFileHandle(FileHandle, ScriptPath); 1918 1919 ShellCloseFile(&FileHandle); 2862 // 2863 // get the argc and argv updated for scripts 2864 // 2865 Status = UpdateArgcArgv(ParamProtocol, CmdLine, &Argv, &Argc); 2866 if (!EFI_ERROR(Status)) { 2867 2868 if (Handle == NULL) { 2869 // 2870 // open the file 2871 // 2872 Status = ShellOpenFileByName(ScriptPath, &FileHandle, EFI_FILE_MODE_READ, 0); 2873 if (!EFI_ERROR(Status)) { 2874 // 2875 // run it 2876 // 2877 Status = RunScriptFileHandle(FileHandle, ScriptPath); 2878 2879 // 2880 // now close the file 2881 // 2882 ShellCloseFile(&FileHandle); 2883 } 2884 } else { 2885 Status = RunScriptFileHandle(Handle, ScriptPath); 2886 } 2887 } 2888 2889 // 2890 // This is guarenteed to be called after UpdateArgcArgv no matter what else happened. 2891 // This is safe even if the update API failed. In this case, it may be a no-op. 2892 // 2893 RestoreArgcArgv(ParamProtocol, &Argv, &Argc); 1920 2894 1921 2895 return (Status); 1922 2896 } 2897 2898 /** 2899 Return the pointer to the first occurance of any character from a list of characters 2900 2901 @param[in] String the string to parse 2902 @param[in] CharacterList the list of character to look for 2903 @param[in] EscapeCharacter An escape character to skip 2904 2905 @return the location of the first character in the string 2906 @retval CHAR_NULL no instance of any character in CharacterList was found in String 2907 **/ 2908 CONST CHAR16* 2909 EFIAPI 2910 FindFirstCharacter( 2911 IN CONST CHAR16 *String, 2912 IN CONST CHAR16 *CharacterList, 2913 IN CONST CHAR16 EscapeCharacter 2914 ) 2915 { 2916 UINT32 WalkChar; 2917 UINT32 WalkStr; 2918 2919 for (WalkStr = 0; WalkStr < StrLen(String); WalkStr++) { 2920 if (String[WalkStr] == EscapeCharacter) { 2921 WalkStr++; 2922 continue; 2923 } 2924 for (WalkChar = 0; WalkChar < StrLen(CharacterList); WalkChar++) { 2925 if (String[WalkStr] == CharacterList[WalkChar]) { 2926 return (&String[WalkStr]); 2927 } 2928 } 2929 } 2930 return (String + StrLen(String)); 2931 } -
trunk/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/Shell/Shell.h
r48674 r58459 2 2 function definitions for internal to shell functions. 3 3 4 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR> 4 (C) Copyright 2014, Hewlett-Packard Development Company, L.P. 5 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR> 5 6 This program and the accompanying materials 6 7 are licensed and made available under the terms and conditions of the BSD License … … 20 21 21 22 #include <Guid/ShellVariableGuid.h> 23 #include <Guid/ShellAliasGuid.h> 22 24 23 25 #include <Protocol/LoadedImage.h> … … 46 48 #include <Library/HandleParsingLib.h> 47 49 #include <Library/PathLib.h> 50 #include <Library/FileHandleLib.h> 48 51 49 52 #include "ShellParametersProtocol.h" … … 53 56 #include "ShellManParser.h" 54 57 #include "ConsoleWrappers.h" 58 #include "FileHandleWrappers.h" 55 59 56 60 typedef struct { … … 69 73 UINT32 NoVersion:1; ///< Was "-noversion" found on command line. 70 74 UINT32 Delay:1; ///< Was "-delay[:n] found on command line 71 UINT32 Reserved:8; ///< Extra bits 75 UINT32 Exit:1; ///< Was "-_exit" found on command line 76 UINT32 Reserved:7; ///< Extra bits 72 77 } SHELL_BITS; 73 78 … … 108 113 SHELL_PROTOCOL_HANDLE_LIST OldShellList; ///< List of other instances to reinstall when closing. 109 114 SPLIT_LIST SplitList; ///< List of Splits in FILO stack. 110 EFI_HANDLE CtrlCNotifyHandle1;///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.111 EFI_HANDLE CtrlCNotifyHandle2;///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.112 EFI_HANDLE CtrlCNotifyHandle3;///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.113 EFI_HANDLE CtrlCNotifyHandle4;///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.114 EFI_HANDLE CtrlSNotifyHandle1;///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.115 EFI_HANDLE CtrlSNotifyHandle2;///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.116 EFI_HANDLE CtrlSNotifyHandle3;///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.117 EFI_HANDLE CtrlSNotifyHandle4;///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.115 VOID *CtrlCNotifyHandle1; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify. 116 VOID *CtrlCNotifyHandle2; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify. 117 VOID *CtrlCNotifyHandle3; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify. 118 VOID *CtrlCNotifyHandle4; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify. 119 VOID *CtrlSNotifyHandle1; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify. 120 VOID *CtrlSNotifyHandle2; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify. 121 VOID *CtrlSNotifyHandle3; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify. 122 VOID *CtrlSNotifyHandle4; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify. 118 123 BOOLEAN HaltOutput; ///< TRUE to start a CTRL-S halt. 119 124 } SHELL_INFO; 120 125 121 126 extern SHELL_INFO ShellInfoObject; 127 128 typedef enum { 129 Internal_Command, 130 Script_File_Name, 131 Efi_Application, 132 File_Sys_Change, 133 Unknown_Invalid 134 } SHELL_OPERATION_TYPES; 135 136 /** 137 Converts the command line to it's post-processed form. this replaces variables and alias' per UEFI Shell spec. 138 139 @param[in,out] CmdLine pointer to the command line to update 140 141 @retval EFI_SUCCESS The operation was successful 142 @retval EFI_OUT_OF_RESOURCES A memory allocation failed. 143 @return some other error occured 144 **/ 145 EFI_STATUS 146 EFIAPI 147 ProcessCommandLineToFinal( 148 IN OUT CHAR16 **CmdLine 149 ); 150 151 /** 152 Function to update the shell variable "lasterror". 153 154 @param[in] ErrorCode the error code to put into lasterror 155 **/ 156 EFI_STATUS 157 EFIAPI 158 SetLastError( 159 IN CONST SHELL_STATUS ErrorCode 160 ); 122 161 123 162 /** … … 290 329 291 330 @param[in] ScriptPath Pointer to the script file name (including file system path). 331 @param[in] Handle the handle of the script file already opened. 332 @param[in] CmdLine the command line to run. 333 @param[in] ParamProtocol the shell parameters protocol pointer 292 334 293 335 @retval EFI_SUCCESS the script completed sucessfully … … 296 338 EFIAPI 297 339 RunScriptFile ( 298 IN CONST CHAR16 *ScriptPath 299 ); 300 340 IN CONST CHAR16 *ScriptPath, 341 IN SHELL_FILE_HANDLE Handle OPTIONAL, 342 IN CONST CHAR16 *CmdLine, 343 IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol 344 ); 345 346 /** 347 Return the pointer to the first occurance of any character from a list of characters 348 349 @param[in] String the string to parse 350 @param[in] CharacterList the list of character to look for 351 @param[in] EscapeCharacter An escape character to skip 352 353 @return the location of the first character in the string 354 @retval CHAR_NULL no instance of any character in CharacterList was found in String 355 **/ 356 CONST CHAR16* 357 EFIAPI 358 FindFirstCharacter( 359 IN CONST CHAR16 *String, 360 IN CONST CHAR16 *CharacterList, 361 IN CONST CHAR16 EscapeCharacter 362 ); 301 363 302 364 #endif //_SHELL_INTERNAL_HEADER_ -
trunk/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/Shell/Shell.inf
r48674 r58459 2 2 # This is the shell application 3 3 # 4 # Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR> 4 # Copyright (c) 2013, Hewlett-Packard Development Company, L.P. 5 # Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR> 5 6 # 6 7 # This program and the accompanying materials … … 73 74 74 75 [Guids] 75 gShellVariableGuid # ALWAYS_CONSUMED76 gShellMapGuid # ALWAYS_CONSUMED77 gShellAliasGuid # ALWAYS_CONSUMED76 gShellVariableGuid ## CONSUMES ## GUID 77 gShellMapGuid ## CONSUMES ## GUID 78 gShellAliasGuid ## CONSUMES ## GUID 78 79 79 80 [Protocols] 80 gEfiShellProtocolGuid # ALWAYS_PRODUCED81 # SOMETIMES_CONSUMED82 gEfiShellParametersProtocolGuid # ALWAYS_PRODUCED83 # SOMETIMES_CONSUMED81 gEfiShellProtocolGuid ## PRODUCES 82 ## SOMETIMES_CONSUMES 83 gEfiShellParametersProtocolGuid ## PRODUCES 84 ## SOMETIMES_CONSUMES 84 85 85 # gEfiShellEnvironment2Guid # SOMETIMES_PRODUCED86 # gEfiShellInterfaceGuid # SOMETIMES_PRODUCED86 # gEfiShellEnvironment2Guid ## SOMETIMES_PRODUCES 87 # gEfiShellInterfaceGuid ## SOMETIMES_PRODUCES 87 88 88 gEfiSimpleTextInputExProtocolGuid # ALWAYS_CONSUMED 89 gEfiSimpleTextInProtocolGuid # ALWAYS_CONSUMED 90 gEfiSimpleTextOutProtocolGuid # ALWAYS_CONSUMED 91 gEfiSimpleFileSystemProtocolGuid # ALWAYS_CONSUMED 92 gEfiLoadedImageProtocolGuid # ALWAYS_CONSUMED 93 gEfiComponentName2ProtocolGuid # ALWAYS_CONSUMED 94 gEfiUnicodeCollation2ProtocolGuid # ALWAYS_CONSUMED 95 gEfiDevicePathProtocolGuid # ALWAYS_CONSUMED 96 gEfiDevicePathToTextProtocolGuid # ALWAYS_CONSUMED 89 gEfiSimpleTextInputExProtocolGuid ## CONSUMES 90 gEfiSimpleTextInProtocolGuid ## CONSUMES 91 gEfiSimpleTextOutProtocolGuid ## CONSUMES 92 gEfiSimpleFileSystemProtocolGuid ## CONSUMES 93 gEfiLoadedImageProtocolGuid ## CONSUMES 94 gEfiComponentName2ProtocolGuid ## CONSUMES 95 gEfiUnicodeCollation2ProtocolGuid ## CONSUMES 96 gEfiDevicePathProtocolGuid ## CONSUMES 97 97 98 98 [Pcd] 99 gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel # ALWAYS_CONSUMED 100 gEfiShellPkgTokenSpaceGuid.PcdShellSupportOldProtocols # ALWAYS_CONSUMED 101 gEfiShellPkgTokenSpaceGuid.PcdShellRequireHiiPlatform # ALWAYS_CONSUMED 102 gEfiShellPkgTokenSpaceGuid.PcdShellSupportFrameworkHii # ALWAYS_CONSUMED 103 gEfiShellPkgTokenSpaceGuid.PcdShellPageBreakDefault # ALWAYS_CONSUMED 104 gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize # ALWAYS_CONSUMED 105 gEfiShellPkgTokenSpaceGuid.PcdShellInsertModeDefault # ALWAYS_CONSUMED 106 gEfiShellPkgTokenSpaceGuid.PcdShellScreenLogCount # ALWAYS_CONSUMED 107 gEfiShellPkgTokenSpaceGuid.PcdShellMapNameLength # ALWAYS_CONSUMED 108 gEfiShellPkgTokenSpaceGuid.PcdShellPrintBufferSize # ALWAYS_CONSUMED 109 gEfiShellPkgTokenSpaceGuid.PcdShellForceConsole # ALWAYS_CONSUMED 99 gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel ## CONSUMES 100 gEfiShellPkgTokenSpaceGuid.PcdShellSupportOldProtocols ## CONSUMES 101 gEfiShellPkgTokenSpaceGuid.PcdShellRequireHiiPlatform ## CONSUMES 102 gEfiShellPkgTokenSpaceGuid.PcdShellSupportFrameworkHii ## CONSUMES 103 gEfiShellPkgTokenSpaceGuid.PcdShellPageBreakDefault ## CONSUMES 104 gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize ## CONSUMES 105 gEfiShellPkgTokenSpaceGuid.PcdShellInsertModeDefault ## CONSUMES 106 gEfiShellPkgTokenSpaceGuid.PcdShellScreenLogCount ## CONSUMES 107 gEfiShellPkgTokenSpaceGuid.PcdShellMapNameLength ## CONSUMES 108 gEfiShellPkgTokenSpaceGuid.PcdShellPrintBufferSize ## CONSUMES 109 gEfiShellPkgTokenSpaceGuid.PcdShellForceConsole ## CONSUMES 110 gEfiShellPkgTokenSpaceGuid.PcdShellSupplier ## CONSUMES 110 111 -
trunk/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/Shell/ShellEnvVar.c
r48674 r58459 2 2 function declarations for shell environment functions. 3 3 4 Copyright (c) 2009 - 201 1, Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR> 5 5 This program and the accompanying materials 6 6 are licensed and made available under the terms and conditions of the BSD License … … 13 13 **/ 14 14 15 #include <Uefi.h> 16 #include <ShellBase.h> 17 18 #include <Guid/ShellVariableGuid.h> 19 20 #include <Library/BaseLib.h> 21 #include <Library/UefiRuntimeServicesTableLib.h> 22 #include <Library/MemoryAllocationLib.h> 23 #include <Library/DebugLib.h> 24 #include <Library/BaseMemoryLib.h> 25 26 #include "ShellEnvVar.h" 15 #include "Shell.h" 16 17 #define INIT_NAME_BUFFER_SIZE 128 18 #define INIT_DATA_BUFFER_SIZE 1024 27 19 28 20 /** … … 106 98 107 99 for ( Node = (ENV_VAR_LIST*)GetFirstNode(List) 108 ; IsListEmpty(List)100 ; !IsListEmpty(List) 109 101 ; Node = (ENV_VAR_LIST*)GetFirstNode(List) 110 102 ){ … … 137 129 CHAR16 *VariableName; 138 130 UINTN NameSize; 139 UINT64 MaxStorSize; 140 UINT64 RemStorSize; 141 UINT64 MaxVarSize; 131 UINTN NameBufferSize; 142 132 EFI_STATUS Status; 143 133 EFI_GUID Guid; 144 134 UINTN ValSize; 135 UINTN ValBufferSize; 145 136 ENV_VAR_LIST *VarList; 146 137 … … 148 139 return (EFI_INVALID_PARAMETER); 149 140 } 150 151 if (gRT->Hdr.Revision >= EFI_2_00_SYSTEM_TABLE_REVISION) { 152 Status = gRT->QueryVariableInfo(EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS, &MaxStorSize, &RemStorSize, &MaxVarSize); 153 if (EFI_ERROR(Status)) { 154 return (Status); 155 } 156 } else { 157 Status = EFI_SUCCESS; 158 MaxVarSize = 16384; 159 } 160 161 NameSize = (UINTN)MaxVarSize; 162 VariableName = AllocateZeroPool(NameSize); 141 142 Status = EFI_SUCCESS; 143 144 ValBufferSize = INIT_DATA_BUFFER_SIZE; 145 NameBufferSize = INIT_NAME_BUFFER_SIZE; 146 VariableName = AllocateZeroPool(NameBufferSize); 163 147 if (VariableName == NULL) { 164 148 return (EFI_OUT_OF_RESOURCES); 165 149 } 166 StrCpy(VariableName, L"");150 *VariableName = CHAR_NULL; 167 151 168 152 while (!EFI_ERROR(Status)) { 169 NameSize = (UINTN)MaxVarSize;153 NameSize = NameBufferSize; 170 154 Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid); 171 155 if (Status == EFI_NOT_FOUND){ 172 156 Status = EFI_SUCCESS; 173 157 break; 174 } 158 } else if (Status == EFI_BUFFER_TOO_SMALL) { 159 NameBufferSize = NameSize > NameBufferSize * 2 ? NameSize : NameBufferSize * 2; 160 SHELL_FREE_NON_NULL(VariableName); 161 VariableName = AllocateZeroPool(NameBufferSize); 162 if (VariableName == NULL) { 163 Status = EFI_OUT_OF_RESOURCES; 164 break; 165 } 166 NameSize = NameBufferSize; 167 Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid); 168 } 169 175 170 if (!EFI_ERROR(Status) && CompareGuid(&Guid, &gShellVariableGuid)){ 176 171 VarList = AllocateZeroPool(sizeof(ENV_VAR_LIST)); … … 178 173 Status = EFI_OUT_OF_RESOURCES; 179 174 } else { 180 ValSize = 0; 175 ValSize = ValBufferSize; 176 VarList->Val = AllocateZeroPool(ValSize); 177 if (VarList->Val == NULL) { 178 SHELL_FREE_NON_NULL(VarList); 179 Status = EFI_OUT_OF_RESOURCES; 180 break; 181 } 181 182 Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(VariableName, &VarList->Atts, &ValSize, VarList->Val); 182 183 if (Status == EFI_BUFFER_TOO_SMALL){ 183 VarList->Val = AllocateZeroPool(ValSize); 184 ValBufferSize = ValSize > ValBufferSize * 2 ? ValSize : ValBufferSize * 2; 185 SHELL_FREE_NON_NULL (VarList->Val); 186 VarList->Val = AllocateZeroPool(ValBufferSize); 184 187 if (VarList->Val == NULL) { 185 188 SHELL_FREE_NON_NULL(VarList); 186 189 Status = EFI_OUT_OF_RESOURCES; 187 } else { 188 Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(VariableName, &VarList->Atts, &ValSize, VarList->Val); 190 break; 189 191 } 192 193 ValSize = ValBufferSize; 194 Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(VariableName, &VarList->Atts, &ValSize, VarList->Val); 190 195 } 191 if (!EFI_ERROR(Status) && VarList != NULL) {192 VarList->Key = Allocate ZeroPool(StrSize(VariableName));196 if (!EFI_ERROR(Status)) { 197 VarList->Key = AllocateCopyPool(StrSize(VariableName), VariableName); 193 198 if (VarList->Key == NULL) { 194 199 SHELL_FREE_NON_NULL(VarList->Val); … … 196 201 Status = EFI_OUT_OF_RESOURCES; 197 202 } else { 198 StrCpy(VarList->Key, VariableName);199 203 InsertTailList(ListHead, &VarList->Link); 200 204 } 205 } else { 206 SHELL_FREE_NON_NULL(VarList->Val); 207 SHELL_FREE_NON_NULL(VarList); 201 208 } 202 } 209 } // if (VarList == NULL) ... else ... 203 210 } // compare guid 204 211 } // while 205 FreePool(VariableName);212 SHELL_FREE_NON_NULL (VariableName); 206 213 207 214 if (EFI_ERROR(Status)) { … … 298 305 ENV_VAR_LIST *VarList; 299 306 ENV_VAR_LIST *Node; 300 UINTN NewSize;301 307 302 308 VarList = NULL; … … 319 325 ASSERT(StrStr(CurrentString, L"=") != NULL); 320 326 Node = AllocateZeroPool(sizeof(ENV_VAR_LIST)); 321 ASSERT(Node != NULL); 327 if (Node == NULL) { 328 SetEnvironmentVariableList(&VarList->Link); 329 return (EFI_OUT_OF_RESOURCES); 330 } 331 322 332 Node->Key = AllocateZeroPool((StrStr(CurrentString, L"=") - CurrentString + 1) * sizeof(CHAR16)); 323 ASSERT(Node->Key != NULL); 333 if (Node->Key == NULL) { 334 SHELL_FREE_NON_NULL(Node); 335 SetEnvironmentVariableList(&VarList->Link); 336 return (EFI_OUT_OF_RESOURCES); 337 } 338 339 // 340 // Copy the string into the Key, leaving the last character allocated as NULL to terminate 341 // 324 342 StrnCpy(Node->Key, CurrentString, StrStr(CurrentString, L"=") - CurrentString); 325 NewSize = StrSize(CurrentString); 326 NewSize -= StrLen(Node->Key) - 1; 327 Node->Val = AllocateZeroPool(NewSize); 328 ASSERT(Node->Val != NULL); 329 StrCpy(Node->Val, CurrentString + StrLen(Node->Key) + 1); 343 344 // 345 // ValueSize = TotalSize - already removed size - size for '=' + size for terminator (the last 2 items cancel each other) 346 // 347 Node->Val = AllocateCopyPool(StrSize(CurrentString) - StrSize(Node->Key), CurrentString + StrLen(Node->Key) + 1); 348 if (Node->Val == NULL) { 349 SHELL_FREE_NON_NULL(Node->Key); 350 SHELL_FREE_NON_NULL(Node); 351 SetEnvironmentVariableList(&VarList->Link); 352 return (EFI_OUT_OF_RESOURCES); 353 } 354 330 355 Node->Atts = EFI_VARIABLE_BOOTSERVICE_ACCESS; 331 356 332 357 if (VarList == NULL) { 333 358 VarList = AllocateZeroPool(sizeof(ENV_VAR_LIST)); 334 ASSERT(VarList != NULL); 359 if (VarList == NULL) { 360 SHELL_FREE_NON_NULL(Node->Key); 361 SHELL_FREE_NON_NULL(Node->Val); 362 SHELL_FREE_NON_NULL(Node); 363 return (EFI_OUT_OF_RESOURCES); 364 } 335 365 InitializeListHead(&VarList->Link); 336 366 } -
trunk/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/Shell/ShellManParser.c
r48674 r58459 2 2 Provides interface to shell MAN file parser. 3 3 4 Copyright (c) 2009 - 201 1, Intel Corporation. All rights reserved.<BR>4 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR> 5 5 This program and the accompanying materials 6 6 are licensed and made available under the terms and conditions of the BSD License … … 40 40 // 41 41 if (StrnCmp(ManFileName+StrLen(ManFileName)-4, L".man", 4)==0) { 42 Buffer = AllocateZeroPool(StrSize(ManFileName)); 43 if (Buffer != NULL) { 44 StrCpy(Buffer, ManFileName); 45 } 42 Buffer = AllocateCopyPool(StrSize(ManFileName), ManFileName); 46 43 } else { 47 44 Buffer = AllocateZeroPool(StrSize(ManFileName) + 4*sizeof(CHAR16)); 48 45 if (Buffer != NULL) { 49 Str Cpy(Buffer, ManFileName);50 Str Cat(Buffer, L".man");46 StrnCpy(Buffer, ManFileName, StrLen(ManFileName)); 47 StrnCat(Buffer, L".man", 4); 51 48 } 52 49 } … … 375 372 CHAR16 *TitleEnd; 376 373 CHAR16 *CurrentLocation; 374 UINTN TitleLength; 375 CONST CHAR16 StartString[] = L".TH "; 376 CONST CHAR16 EndString[] = L" 0 "; 377 377 378 378 if ( Buffer == NULL … … 385 385 Status = EFI_SUCCESS; 386 386 387 TitleString = AllocateZeroPool((7*sizeof(CHAR16)) + StrSize(Command)); 387 // 388 // more characters for StartString and EndString 389 // 390 TitleLength = StrSize(Command) + (StrLen(StartString) + StrLen(EndString)) * sizeof(CHAR16); 391 TitleString = AllocateZeroPool(TitleLength); 388 392 if (TitleString == NULL) { 389 393 return (EFI_OUT_OF_RESOURCES); 390 394 } 391 Str Cpy(TitleString, L".TH ");392 Str Cat(TitleString, Command);393 Str Cat(TitleString, L" 0 ");395 StrnCpy(TitleString, StartString, TitleLength/sizeof(CHAR16) - 1); 396 StrnCat(TitleString, Command, TitleLength/sizeof(CHAR16) - 1 - StrLen(TitleString)); 397 StrnCat(TitleString, EndString, TitleLength/sizeof(CHAR16) - 1 - StrLen(TitleString)); 394 398 395 399 CurrentLocation = StrStr(*Buffer, TitleString); … … 468 472 UINTN TitleLen; 469 473 BOOLEAN Found; 474 UINTN TitleSize; 470 475 471 476 if ( Handle == NULL … … 485 490 } 486 491 487 TitleString = AllocateZeroPool((4*sizeof(CHAR16)) + StrSize(Command)); 492 TitleSize = (4*sizeof(CHAR16)) + StrSize(Command); 493 TitleString = AllocateZeroPool(TitleSize); 488 494 if (TitleString == NULL) { 489 495 FreePool(ReadLine); 490 496 return (EFI_OUT_OF_RESOURCES); 491 497 } 492 StrCpy(TitleString, L".TH "); 493 StrCat(TitleString, Command); 498 StrnCpy(TitleString, L".TH ", TitleSize/sizeof(CHAR16) - 1); 499 StrnCat(TitleString, Command, TitleSize/sizeof(CHAR16) - 1 - StrLen(TitleString)); 500 494 501 TitleLen = StrLen(TitleString); 495 502 for (;!ShellFileHandleEof(Handle);Size = 1024) { … … 526 533 break; 527 534 } 528 Str Cpy(*BriefDesc, TitleEnd);535 StrnCpy(*BriefDesc, TitleEnd, (*BriefSize)/sizeof(CHAR16) - 1); 529 536 } 530 537 break; … … 599 606 BriefSize = 0; 600 607 TempString = NULL; 608 Ascii = FALSE; 601 609 // 602 610 // See if it's in HII first -
trunk/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/Shell/ShellParametersProtocol.c
r48674 r58459 3 3 manipulation, and initialization of EFI_SHELL_PARAMETERS_PROTOCOL. 4 4 5 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR> 5 Copyright (C) 2014, Red Hat, Inc. 6 Copyright (c) 2013 Hewlett-Packard Development Company, L.P. 7 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR> 6 8 This program and the accompanying materials 7 9 are licensed and made available under the terms and conditions of the BSD License … … 14 16 **/ 15 17 16 #include "ShellParametersProtocol.h" 17 #include "ConsoleWrappers.h" 18 19 /** 20 return the next parameter from a command line string; 18 #include "Shell.h" 19 20 /** 21 Return the next parameter's end from a command line string. 22 23 @param[in] String the string to parse 24 **/ 25 CONST CHAR16* 26 EFIAPI 27 FindEndOfParameter( 28 IN CONST CHAR16 *String 29 ) 30 { 31 CONST CHAR16 *First; 32 CONST CHAR16 *CloseQuote; 33 34 First = FindFirstCharacter(String, L" \"", L'^'); 35 36 // 37 // nothing, all one parameter remaining 38 // 39 if (*First == CHAR_NULL) { 40 return (First); 41 } 42 43 // 44 // If space before a quote (or neither found, i.e. both CHAR_NULL), 45 // then that's the end. 46 // 47 if (*First == L' ') { 48 return (First); 49 } 50 51 CloseQuote = FindFirstCharacter (First+1, L"\"", L'^'); 52 53 // 54 // We did not find a terminator... 55 // 56 if (*CloseQuote == CHAR_NULL) { 57 return (NULL); 58 } 59 60 return (FindEndOfParameter (CloseQuote+1)); 61 } 62 63 /** 64 Return the next parameter from a command line string. 21 65 22 66 This function moves the next parameter from Walker into TempParameter and moves … … 27 71 function. 28 72 73 This will also remove all remaining ^ characters after processing. 74 29 75 @param[in, out] Walker pointer to string of command line. Adjusted to 30 76 reminaing command line on return 31 77 @param[in, out] TempParameter pointer to string of command line item extracted. 32 33 **/ 34 VOID 78 @param[in] Length buffer size of TempParameter. 79 80 @return EFI_INALID_PARAMETER A required parameter was NULL or pointed to a NULL or empty string. 81 @return EFI_NOT_FOUND A closing " could not be found on the specified string 82 **/ 83 EFI_STATUS 35 84 EFIAPI 36 85 GetNextParameter( 37 CHAR16 **Walker, 38 CHAR16 **TempParameter 39 ) 40 { 41 CHAR16 *NextDelim; 42 CHAR16 *TempLoc; 43 44 ASSERT(Walker != NULL); 45 ASSERT(*Walker != NULL); 46 ASSERT(TempParameter != NULL); 47 ASSERT(*TempParameter != NULL); 86 IN OUT CHAR16 **Walker, 87 IN OUT CHAR16 **TempParameter, 88 IN CONST UINTN Length 89 ) 90 { 91 CONST CHAR16 *NextDelim; 92 93 if (Walker == NULL 94 ||*Walker == NULL 95 ||TempParameter == NULL 96 ||*TempParameter == NULL 97 ){ 98 return (EFI_INVALID_PARAMETER); 99 } 100 48 101 49 102 // … … 58 111 // 59 112 if (StrLen(*Walker) == 0) { 60 ASSERT((*Walker)[0] == CHAR_NULL); 61 *Walker = NULL; 62 return; 63 } 64 65 // 66 // we have a quoted parameter 67 // could be the last parameter, but SHOULD have a trailing quote 68 // 69 if ((*Walker)[0] == L'\"') { 70 NextDelim = NULL; 71 for (TempLoc = *Walker + 1 ; TempLoc != NULL && *TempLoc != CHAR_NULL ; TempLoc++) { 72 if (*TempLoc == L'^' && *(TempLoc+1) == L'\"') { 73 TempLoc++; 74 } else if (*TempLoc == L'\"') { 75 NextDelim = TempLoc; 76 break; 77 } 78 } 79 80 if (NextDelim - ((*Walker)+1) == 0) { 81 // 82 // found "" 83 // 84 StrCpy(*TempParameter, L""); 85 *Walker = NextDelim + 1; 86 } else if (NextDelim != NULL) { 87 StrnCpy(*TempParameter, (*Walker)+1, NextDelim - ((*Walker)+1)); 88 *Walker = NextDelim + 1; 89 } else { 90 // 91 // last one... someone forgot the training quote! 92 // 93 StrCpy(*TempParameter, *Walker); 94 *Walker = NULL; 95 } 96 for (TempLoc = *TempParameter ; TempLoc != NULL && *TempLoc != CHAR_NULL ; TempLoc++) { 97 if (*TempLoc == L'^' && *(TempLoc+1) == L'\"') { 98 CopyMem(TempLoc, TempLoc+1, StrSize(TempLoc) - sizeof(TempLoc[0])); 99 } 100 } 101 } else { 102 // 103 // we have a regular parameter (no quote) OR 104 // we have the final parameter (no trailing space) 105 // 106 NextDelim = StrStr((*Walker), L" "); 107 if (NextDelim != NULL) { 108 StrnCpy(*TempParameter, *Walker, NextDelim - (*Walker)); 109 (*TempParameter)[NextDelim - (*Walker)] = CHAR_NULL; 110 *Walker = NextDelim+1; 111 } else { 112 // 113 // last one. 114 // 115 StrCpy(*TempParameter, *Walker); 116 *Walker = NULL; 117 } 118 for (NextDelim = *TempParameter ; NextDelim != NULL && *NextDelim != CHAR_NULL ; NextDelim++) { 119 if (*NextDelim == L'^' && *(NextDelim+1) == L'^') { 120 CopyMem(NextDelim, NextDelim+1, StrSize(NextDelim) - sizeof(NextDelim[0])); 121 } 122 } 123 while ((*TempParameter)[StrLen(*TempParameter)-1] == L' ') { 124 (*TempParameter)[StrLen(*TempParameter)-1] = CHAR_NULL; 125 } 126 while ((*TempParameter)[0] == L' ') { 127 CopyMem(*TempParameter, (*TempParameter)+1, StrSize(*TempParameter) - sizeof((*TempParameter)[0])); 128 } 129 } 130 return; 113 DEBUG_CODE_BEGIN(); 114 *Walker = NULL; 115 DEBUG_CODE_END(); 116 return (EFI_INVALID_PARAMETER); 117 } 118 119 NextDelim = FindEndOfParameter(*Walker); 120 121 if (NextDelim == NULL){ 122 DEBUG_CODE_BEGIN(); 123 *Walker = NULL; 124 DEBUG_CODE_END(); 125 return (EFI_NOT_FOUND); 126 } 127 128 StrnCpy(*TempParameter, (*Walker), NextDelim - *Walker); 129 130 // 131 // Add a CHAR_NULL if we didnt get one via the copy 132 // 133 if (*NextDelim != CHAR_NULL) { 134 (*TempParameter)[NextDelim - *Walker] = CHAR_NULL; 135 } 136 137 // 138 // Update Walker for the next iteration through the function 139 // 140 *Walker = (CHAR16*)NextDelim; 141 142 // 143 // Remove any non-escaped quotes in the string 144 // Remove any remaining escape characters in the string 145 // 146 for (NextDelim = FindFirstCharacter(*TempParameter, L"\"^", CHAR_NULL) 147 ; *NextDelim != CHAR_NULL 148 ; NextDelim = FindFirstCharacter(NextDelim, L"\"^", CHAR_NULL) 149 ) { 150 if (*NextDelim == L'^') { 151 152 // 153 // eliminate the escape ^ 154 // 155 CopyMem ((CHAR16*)NextDelim, NextDelim + 1, StrSize (NextDelim + 1)); 156 NextDelim++; 157 } else if (*NextDelim == L'\"') { 158 159 // 160 // eliminate the unescaped quote 161 // 162 CopyMem ((CHAR16*)NextDelim, NextDelim + 1, StrSize (NextDelim + 1)); 163 } 164 } 165 166 return EFI_SUCCESS; 131 167 } 132 168 … … 137 173 parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL. this supports space 138 174 delimited and quote surrounded parameter definition. 175 176 All special character processing (alias, environment variable, redirection, 177 etc... must be complete before calling this API. 139 178 140 179 @param[in] CommandLine String of command line to parse … … 177 216 , Walker = (CHAR16*)CommandLine 178 217 ; Walker != NULL && *Walker != CHAR_NULL 179 ; GetNextParameter(&Walker, &TempParameter) 180 , Count++ 181 ); 182 183 /* Count = 0; 184 Walker = (CHAR16*)CommandLine; 185 while(Walker != NULL) { 186 GetNextParameter(&Walker, &TempParameter); 187 Count++; 188 } 189 */ 218 ; Count++ 219 ) { 220 if (EFI_ERROR(GetNextParameter(&Walker, &TempParameter, Size))) { 221 break; 222 } 223 } 224 190 225 // 191 226 // lets allocate the pointer array … … 193 228 (*Argv) = AllocateZeroPool((Count)*sizeof(CHAR16*)); 194 229 if (*Argv == NULL) { 230 SHELL_FREE_NON_NULL(TempParameter); 195 231 return (EFI_OUT_OF_RESOURCES); 196 232 } … … 200 236 while(Walker != NULL && *Walker != CHAR_NULL) { 201 237 SetMem16(TempParameter, Size, CHAR_NULL); 202 GetNextParameter(&Walker, &TempParameter); 203 NewParam = AllocateZeroPool(StrSize(TempParameter)); 204 ASSERT(NewParam != NULL); 205 StrCpy(NewParam, TempParameter); 238 if (EFI_ERROR(GetNextParameter(&Walker, &TempParameter, Size))) { 239 SHELL_FREE_NON_NULL(TempParameter); 240 return (EFI_INVALID_PARAMETER); 241 } 242 243 NewParam = AllocateCopyPool(StrSize(TempParameter), TempParameter); 244 if (NewParam == NULL){ 245 SHELL_FREE_NON_NULL(TempParameter); 246 return (EFI_OUT_OF_RESOURCES); 247 } 206 248 ((CHAR16**)(*Argv))[(*Argc)] = NewParam; 207 249 (*Argc)++; 208 250 } 209 251 ASSERT(Count >= (*Argc)); 252 SHELL_FREE_NON_NULL(TempParameter); 210 253 return (EFI_SUCCESS); 211 254 } … … 290 333 // Build the full command line 291 334 // 292 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, &FullCommandLine);335 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, FullCommandLine); 293 336 if (Status == EFI_BUFFER_TOO_SMALL) { 294 337 FullCommandLine = AllocateZeroPool(Size + LoadedImage->LoadOptionsSize); 295 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, &FullCommandLine);338 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, FullCommandLine); 296 339 } 297 340 if (Status == EFI_NOT_FOUND) { … … 313 356 } 314 357 if (FullCommandLine != NULL) { 315 if (LoadedImage->LoadOptionsSize != 0){ 316 StrCpy(FullCommandLine, LoadedImage->LoadOptions); 317 } 358 CopyMem (FullCommandLine, LoadedImage->LoadOptions, LoadedImage->LoadOptionsSize); 318 359 // 319 360 // Populate Argc and Argv … … 524 565 } else { 525 566 Copy = FileName; 567 while(Copy[0] == L' ') { 568 Copy++; 569 } 526 570 if ((TempLocation = StrStr(Copy , L" ")) != NULL) { 527 571 TempLocation[0] = CHAR_NULL; … … 535 579 return (Copy); 536 580 } 581 582 /** 583 Fix a string to only have the environment variable name, removing starting at the first space of whatever is quoted and removing the leading and trailing %. 584 585 @param[in] FileName The filename to start with. 586 587 @retval NULL FileName was invalid. 588 @return The modified FileName. 589 **/ 590 CHAR16* 591 EFIAPI 592 FixVarName ( 593 IN CHAR16 *FileName 594 ) 595 { 596 CHAR16 *Copy; 597 CHAR16 *TempLocation; 598 599 Copy = FileName; 600 601 if (FileName[0] == L'%') { 602 Copy = FileName+1; 603 if ((TempLocation = StrStr(Copy , L"%")) != NULL) { 604 TempLocation[0] = CHAR_NULL; 605 } 606 } 607 608 return (FixFileName(Copy)); 609 } 610 611 /** 612 Remove the unicode file tag from the begining of the file buffer since that will not be 613 used by StdIn. 614 615 @param[in] Handle Pointer to the handle of the file to be processed. 616 617 @retval EFI_SUCCESS The unicode file tag has been moved successfully. 618 **/ 619 EFI_STATUS 620 EFIAPI 621 RemoveFileTag( 622 IN SHELL_FILE_HANDLE *Handle 623 ) 624 { 625 UINTN CharSize; 626 CHAR16 CharBuffer; 627 628 CharSize = sizeof(CHAR16); 629 CharBuffer = 0; 630 gEfiShellProtocol->ReadFile(*Handle, &CharSize, &CharBuffer); 631 if (CharBuffer != gUnicodeFileTag) { 632 gEfiShellProtocol->SetFilePosition(*Handle, 0); 633 } 634 return (EFI_SUCCESS); 635 } 636 637 /** 638 Write the unicode file tag to the specified file. 639 640 It is the caller's responsibility to ensure that 641 ShellInfoObject.NewEfiShellProtocol has been initialized before calling this 642 function. 643 644 @param[in] FileHandle The file to write the unicode file tag to. 645 646 @return Status code from ShellInfoObject.NewEfiShellProtocol->WriteFile. 647 **/ 648 EFI_STATUS 649 WriteFileTag ( 650 IN SHELL_FILE_HANDLE FileHandle 651 ) 652 { 653 CHAR16 FileTag; 654 UINTN Size; 655 EFI_STATUS Status; 656 657 FileTag = gUnicodeFileTag; 658 Size = sizeof FileTag; 659 Status = ShellInfoObject.NewEfiShellProtocol->WriteFile (FileHandle, &Size, 660 &FileTag); 661 ASSERT (EFI_ERROR (Status) || Size == sizeof FileTag); 662 return Status; 663 } 664 537 665 538 666 /** … … 581 709 BOOLEAN ErrAppend; 582 710 UINTN Size; 583 CHAR16 TagBuffer[2];584 711 SPLIT_LIST *Split; 585 712 CHAR16 *FirstLocation; … … 607 734 SystemTableInfo->ConOut = gST->ConOut; 608 735 SystemTableInfo->ConOutHandle = gST->ConsoleOutHandle; 609 SystemTableInfo-> ConErr= gST->StdErr;610 SystemTableInfo-> ConErrHandle = gST->StandardErrorHandle;736 SystemTableInfo->ErrOut = gST->StdErr; 737 SystemTableInfo->ErrOutHandle = gST->StandardErrorHandle; 611 738 *OldStdIn = ShellParameters->StdIn; 612 739 *OldStdOut = ShellParameters->StdOut; … … 886 1013 // re-populate the string to support any filenames that were in quotes. 887 1014 // 888 Str Cpy(CommandLineCopy, NewCommandLine);1015 StrnCpy(CommandLineCopy, NewCommandLine, StrLen(NewCommandLine)); 889 1016 890 1017 if (FirstLocation != CommandLineCopy + StrLen(CommandLineCopy) … … 912 1039 } 913 1040 if (StdErrVarName != NULL) { 914 if ((StdErrVarName = Fix FileName(StdErrVarName)) == NULL) {1041 if ((StdErrVarName = FixVarName(StdErrVarName)) == NULL) { 915 1042 Status = EFI_INVALID_PARAMETER; 916 1043 } 917 1044 } 918 1045 if (StdOutVarName != NULL) { 919 if ((StdOutVarName = Fix FileName(StdOutVarName)) == NULL) {1046 if ((StdOutVarName = FixVarName(StdOutVarName)) == NULL) { 920 1047 Status = EFI_INVALID_PARAMETER; 921 1048 } 922 1049 } 923 1050 if (StdInVarName != NULL) { 924 if ((StdInVarName = Fix FileName(StdInVarName)) == NULL) {1051 if ((StdInVarName = FixVarName(StdInVarName)) == NULL) { 925 1052 Status = EFI_INVALID_PARAMETER; 926 1053 } … … 993 1120 Status = ShellOpenFileByName(StdErrFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0); 994 1121 if (!ErrAppend && ErrUnicode && !EFI_ERROR(Status)) { 995 // 996 // Write out the gUnicodeFileTag 997 // 998 Size = sizeof(CHAR16); 999 TagBuffer[0] = gUnicodeFileTag; 1000 TagBuffer[1] = CHAR_NULL; 1001 ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer); 1122 Status = WriteFileTag (TempHandle); 1002 1123 } 1003 1124 if (!ErrUnicode && !EFI_ERROR(Status)) { … … 1007 1128 if (!EFI_ERROR(Status)) { 1008 1129 ShellParameters->StdErr = TempHandle; 1009 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle );1130 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr); 1010 1131 } 1011 1132 } … … 1028 1149 //no-op 1029 1150 } else if (!OutAppend && OutUnicode && !EFI_ERROR(Status)) { 1030 // 1031 // Write out the gUnicodeFileTag 1032 // 1033 Size = sizeof(CHAR16); 1034 TagBuffer[0] = gUnicodeFileTag; 1035 TagBuffer[1] = CHAR_NULL; 1036 ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer); 1151 Status = WriteFileTag (TempHandle); 1037 1152 } else if (OutAppend) { 1038 //1039 // Move to end of file1040 //1041 1153 Status = ShellInfoObject.NewEfiShellProtocol->GetFileSize(TempHandle, &FileSize); 1042 1154 if (!EFI_ERROR(Status)) { 1043 Status = ShellInfoObject.NewEfiShellProtocol->SetFilePosition(TempHandle, FileSize); 1155 // 1156 // When appending to a new unicode file, write the file tag. 1157 // Otherwise (ie. when appending to a new ASCII file, or an 1158 // existent file with any encoding), just seek to the end. 1159 // 1160 Status = (FileSize == 0 && OutUnicode) ? 1161 WriteFileTag (TempHandle) : 1162 ShellInfoObject.NewEfiShellProtocol->SetFilePosition ( 1163 TempHandle, 1164 FileSize); 1044 1165 } 1045 1166 } … … 1050 1171 if (!EFI_ERROR(Status)) { 1051 1172 ShellParameters->StdOut = TempHandle; 1052 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle );1173 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut); 1053 1174 } 1054 1175 } … … 1068 1189 ASSERT(TempHandle != NULL); 1069 1190 ShellParameters->StdOut = TempHandle; 1070 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle );1191 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut); 1071 1192 } 1072 1193 … … 1084 1205 ASSERT(TempHandle != NULL); 1085 1206 ShellParameters->StdErr = TempHandle; 1086 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle );1207 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr); 1087 1208 } 1088 1209 … … 1117 1238 EFI_FILE_MODE_READ, 1118 1239 0); 1119 if (!InUnicode && !EFI_ERROR(Status)) { 1240 if (InUnicode) { 1241 // 1242 // Chop off the 0xFEFF if it's there... 1243 // 1244 RemoveFileTag(&TempHandle); 1245 } else if (!EFI_ERROR(Status)) { 1246 // 1247 // Create the ASCII->Unicode conversion layer 1248 // 1120 1249 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE); 1121 1250 } … … 1132 1261 1133 1262 if (gST->ConIn == NULL ||gST->ConOut == NULL) { 1134 return (EFI_OUT_OF_RESOURCES); 1135 } 1263 Status = EFI_OUT_OF_RESOURCES; 1264 } 1265 1266 if (Status == EFI_NOT_FOUND) { 1267 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_REDUNDA_REDIR), ShellInfoObject.HiiHandle); 1268 } else if (EFI_ERROR(Status)) { 1269 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_REDIR), ShellInfoObject.HiiHandle); 1270 } 1271 1136 1272 return (Status); 1137 1273 } … … 1198 1334 gST->ConsoleOutHandle = SystemTableInfo->ConOutHandle; 1199 1335 } 1200 if (gST->StdErr != SystemTableInfo-> ConErr) {1336 if (gST->StdErr != SystemTableInfo->ErrOut) { 1201 1337 CloseSimpleTextOutOnFile(gST->StdErr); 1202 gST->StdErr = SystemTableInfo-> ConErr;1203 gST->StandardErrorHandle = SystemTableInfo-> ConErrHandle;1338 gST->StdErr = SystemTableInfo->ErrOut; 1339 gST->StandardErrorHandle = SystemTableInfo->ErrOutHandle; 1204 1340 } 1205 1341 -
trunk/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/Shell/ShellParametersProtocol.h
r48674 r58459 3 3 manipulation, and initialization of EFI_SHELL_PARAMETERS_PROTOCOL. 4 4 5 Copyright (c) 2009 - 201 0, Intel Corporation. All rights reserved.<BR>5 Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR> 6 6 This program and the accompanying materials 7 7 are licensed and made available under the terms and conditions of the BSD License … … 17 17 #define _SHELL_PARAMETERS_PROTOCOL_PROVIDER_HEADER_ 18 18 19 #include <Uefi.h>20 21 #include <Protocol/SimpleFileSystem.h>22 #include <Protocol/EfiShellParameters.h>23 #include <Protocol/LoadedImage.h>24 #include <Protocol/SimpleTextOut.h>25 #include <Protocol/SimpleTextIn.h>26 27 #include <Guid/ShellVariableGuid.h>28 29 #include <Library/UefiBootServicesTableLib.h>30 #include <Library/UefiRuntimeServicesTableLib.h>31 #include <Library/MemoryAllocationLib.h>32 #include <Library/UefiLib.h>33 #include <Library/DebugLib.h>34 #include <Library/ShellLib.h>35 #include <Library/FileHandleLib.h>36 37 #include "ShellEnvVar.h"38 #include "FileHandleWrappers.h"39 19 #include "Shell.h" 40 20 … … 124 104 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; 125 105 EFI_HANDLE ConOutHandle; 126 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * ConErr;127 EFI_HANDLE ConErrHandle;106 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ErrOut; 107 EFI_HANDLE ErrOutHandle; 128 108 } SYSTEM_TABLE_INFO; 129 109 … … 211 191 reminaing command line on return 212 192 @param[in, out] TempParameter pointer to string of command line item extracted. 213 214 **/ 215 VOID 193 @param[in] Length Length of (*TempParameter) in bytes 194 195 @return EFI_INALID_PARAMETER A required parameter was NULL or pointed to a NULL or empty string. 196 @return EFI_NOT_FOUND A closing " could not be found on the specified string 197 **/ 198 EFI_STATUS 216 199 EFIAPI 217 200 GetNextParameter( 218 CHAR16 **Walker, 219 CHAR16 **TempParameter 201 IN OUT CHAR16 **Walker, 202 IN OUT CHAR16 **TempParameter, 203 IN CONST UINTN Length 220 204 ); 221 205 -
trunk/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/Shell/ShellProtocol.c
r48674 r58459 3 3 manipulation, and initialization of EFI_SHELL_PROTOCOL. 4 4 5 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR> 5 (C) Copyright 2014, Hewlett-Packard Development Company, L.P. 6 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR> 6 7 This program and the accompanying materials 7 8 are licensed and made available under the terms and conditions of the BSD License … … 15 16 16 17 #include "Shell.h" 17 #include <Library/FileHandleLib.h> 18 19 #define INIT_NAME_BUFFER_SIZE 128 18 20 19 21 /** … … 117 119 ) 118 120 { 119 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevicePathToText;120 121 EFI_STATUS Status; 121 122 CHAR16 *Temp; … … 123 124 Status = EFI_SUCCESS; 124 125 DEBUG_CODE_BEGIN(); 125 DevicePathToText = NULL; 126 127 Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, 128 NULL, 129 (VOID**)&DevicePathToText); 126 130 127 if (Mapping != NULL) { 131 128 DEBUG((EFI_D_INFO, "Added new map item:\"%S\"\r\n", Mapping)); 132 129 } 133 if (!EFI_ERROR(Status)) { 134 if (DevicePath != NULL) { 135 Temp = DevicePathToText->ConvertDevicePathToText(DevicePath, TRUE, TRUE); 136 DEBUG((EFI_D_INFO, "DevicePath: %S\r\n", Temp)); 137 FreePool(Temp); 138 } 139 } 130 Temp = ConvertDevicePathToText(DevicePath, TRUE, TRUE); 131 DEBUG((EFI_D_INFO, "DevicePath: %S\r\n", Temp)); 132 FreePool(Temp); 133 140 134 DEBUG_CODE_END(); 141 135 return (Status); … … 468 462 // 469 463 ASSERT((PathForReturn == NULL && PathSize == 0) || (PathForReturn != NULL)); 470 PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, L"\\", 1);471 464 472 465 AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePath), FilePath); 466 ASSERT (AlignedNode != NULL); 467 468 // File Path Device Path Nodes 'can optionally add a "\" separator to 469 // the beginning and/or the end of the Path Name string.' 470 // (UEFI Spec 2.4 section 9.3.6.4). 471 // If necessary, add a "\", but otherwise don't 472 // (This is specified in the above section, and also implied by the 473 // UEFI Shell spec section 3.7) 474 if ((PathSize != 0) && 475 (PathForReturn != NULL) && 476 (PathForReturn[PathSize - 1] != L'\\') && 477 (AlignedNode->PathName[0] != L'\\')) { 478 PathForReturn = StrnCatGrow (&PathForReturn, &PathSize, L"\\", 1); 479 } 480 473 481 PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, AlignedNode->PathName, 0); 474 482 FreePool(AlignedNode); … … 525 533 return (NULL); 526 534 } 527 Size = StrSize(Cwd); 528 Size += StrSize(Path); 535 Size = StrSize(Cwd) + StrSize(Path) - sizeof(CHAR16); 529 536 NewPath = AllocateZeroPool(Size); 530 537 if (NewPath == NULL) { 531 538 return (NULL); 532 539 } 533 Str Cpy(NewPath, Cwd);540 StrnCpy(NewPath, Cwd, Size/sizeof(CHAR16)-1); 534 541 if (*Path == L'\\') { 535 542 Path++; 536 543 while (PathRemoveLastItem(NewPath)) ; 537 544 } 538 Str Cat(NewPath, Path);545 StrnCat(NewPath, Path, Size/sizeof(CHAR16) - 1 - StrLen(NewPath)); 539 546 DevicePathForReturn = EfiShellGetDevicePathFromFilePath(NewPath); 540 547 FreePool(NewPath); … … 649 656 EFI_STATUS Status; 650 657 EFI_COMPONENT_NAME2_PROTOCOL *CompName2; 651 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevicePathToText;652 658 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 653 659 EFI_HANDLE *HandleList; … … 656 662 CHAR16 *DeviceNameToReturn; 657 663 CHAR8 *Lang; 658 CHAR8 *TempChar;659 660 664 UINTN ParentControllerCount; 661 665 EFI_HANDLE *ParentControllerBuffer; … … 714 718 continue; 715 719 } 716 if (Language == NULL) { 717 Lang = AllocateZeroPool(AsciiStrSize(CompName2->SupportedLanguages)); 718 if (Lang == NULL) { 719 return (EFI_OUT_OF_RESOURCES); 720 } 721 AsciiStrCpy(Lang, CompName2->SupportedLanguages); 722 TempChar = AsciiStrStr(Lang, ";"); 723 if (TempChar != NULL){ 724 *TempChar = CHAR_NULL; 725 } 726 } else { 727 Lang = AllocateZeroPool(AsciiStrSize(Language)); 728 if (Lang == NULL) { 729 return (EFI_OUT_OF_RESOURCES); 730 } 731 AsciiStrCpy(Lang, Language); 732 } 720 Lang = GetBestLanguageForDriver(CompName2->SupportedLanguages, Language, FALSE); 733 721 Status = CompName2->GetControllerName(CompName2, DeviceHandle, NULL, Lang, &DeviceNameToReturn); 734 722 FreePool(Lang); … … 773 761 continue; 774 762 } 775 if (Language == NULL) { 776 Lang = AllocateZeroPool(AsciiStrSize(CompName2->SupportedLanguages)); 777 if (Lang == NULL) { 778 return (EFI_OUT_OF_RESOURCES); 779 } 780 AsciiStrCpy(Lang, CompName2->SupportedLanguages); 781 TempChar = AsciiStrStr(Lang, ";"); 782 if (TempChar != NULL){ 783 *TempChar = CHAR_NULL; 784 } 785 } else { 786 Lang = AllocateZeroPool(AsciiStrSize(Language)); 787 if (Lang == NULL) { 788 return (EFI_OUT_OF_RESOURCES); 789 } 790 AsciiStrCpy(Lang, Language); 791 } 763 Lang = GetBestLanguageForDriver(CompName2->SupportedLanguages, Language, FALSE); 792 764 Status = CompName2->GetControllerName(CompName2, ParentControllerBuffer[LoopVar], DeviceHandle, Lang, &DeviceNameToReturn); 793 765 FreePool(Lang); … … 817 789 } 818 790 if ((Flags & EFI_DEVICE_NAME_USE_DEVICE_PATH) != 0) { 819 Status = gBS->LocateProtocol( 820 &gEfiDevicePathToTextProtocolGuid, 791 Status = gBS->OpenProtocol( 792 DeviceHandle, 793 &gEfiDevicePathProtocolGuid, 794 (VOID**)&DevicePath, 795 gImageHandle, 821 796 NULL, 822 (VOID**)&DevicePathToText); 823 // 824 // we now have the device path to text protocol 825 // 797 EFI_OPEN_PROTOCOL_GET_PROTOCOL); 826 798 if (!EFI_ERROR(Status)) { 827 Status = gBS->OpenProtocol( 828 DeviceHandle, 829 &gEfiDevicePathProtocolGuid, 830 (VOID**)&DevicePath, 831 gImageHandle, 832 NULL, 833 EFI_OPEN_PROTOCOL_GET_PROTOCOL); 834 if (!EFI_ERROR(Status)) { 835 // 836 // use device path to text on the device path 837 // 838 *BestDeviceName = DevicePathToText->ConvertDevicePathToText(DevicePath, TRUE, TRUE); 839 return (EFI_SUCCESS); 840 } 799 // 800 // use device path to text on the device path 801 // 802 *BestDeviceName = ConvertDevicePathToText(DevicePath, TRUE, TRUE); 803 return (EFI_SUCCESS); 841 804 } 842 805 } … … 996 959 EFI_FILE_PROTOCOL *Handle1; 997 960 EFI_FILE_PROTOCOL *Handle2; 998 EFI_DEVICE_PATH_PROTOCOL *DpCopy;999 961 FILEPATH_DEVICE_PATH *AlignedNode; 1000 962 … … 1006 968 Handle2 = NULL; 1007 969 Handle = NULL; 1008 DpCopy = DevicePath;1009 970 ShellHandle = NULL; 1010 971 FilePathNode = NULL; … … 1187 1148 } 1188 1149 1189 Status = InternalOpenFileDevicePath(DevicePath, FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, FileAttribs); // 0 = no specific file attributes1150 Status = InternalOpenFileDevicePath(DevicePath, FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, FileAttribs); 1190 1151 FreePool(DevicePath); 1191 1152 1192 1153 return(Status); 1154 } 1155 1156 /** 1157 Register a GUID and a localized human readable name for it. 1158 1159 If Guid is not assigned a name, then assign GuidName to Guid. This list of GUID 1160 names must be used whenever a shell command outputs GUID information. 1161 1162 This function is only available when the major and minor versions in the 1163 EfiShellProtocol are greater than or equal to 2 and 1, respectively. 1164 1165 @param[in] Guid A pointer to the GUID being registered. 1166 @param[in] GuidName A pointer to the localized name for the GUID being registered. 1167 1168 @retval EFI_SUCCESS The operation was successful. 1169 @retval EFI_INVALID_PARAMETER Guid was NULL. 1170 @retval EFI_INVALID_PARAMETER GuidName was NULL. 1171 @retval EFI_ACCESS_DENIED Guid already is assigned a name. 1172 **/ 1173 EFI_STATUS 1174 EFIAPI 1175 EfiShellRegisterGuidName( 1176 IN CONST EFI_GUID *Guid, 1177 IN CONST CHAR16 *GuidName 1178 ) 1179 { 1180 return (AddNewGuidNameMapping(Guid, GuidName, NULL)); 1193 1181 } 1194 1182 … … 1360 1348 EFI_STATUS Status; 1361 1349 1350 FileHandle = NULL; 1351 1362 1352 // 1363 1353 // get a handle to the file … … 1402 1392 internal worker function to load and run an image via device path. 1403 1393 1404 @param ParentImageHandle A handle of the image that is executing the specified 1405 command line. 1406 @param DevicePath device path of the file to execute 1407 @param CommandLine Points to the NULL-terminated UCS-2 encoded string 1408 containing the command line. If NULL then the command- 1409 line will be empty. 1410 @param Environment Points to a NULL-terminated array of environment 1411 variables with the format 'x=y', where x is the 1412 environment variable name and y is the value. If this 1413 is NULL, then the current shell environment is used. 1414 @param StatusCode Points to the status code returned by the command. 1394 @param ParentImageHandle A handle of the image that is executing the specified 1395 command line. 1396 @param DevicePath device path of the file to execute 1397 @param CommandLine Points to the NULL-terminated UCS-2 encoded string 1398 containing the command line. If NULL then the command- 1399 line will be empty. 1400 @param Environment Points to a NULL-terminated array of environment 1401 variables with the format 'x=y', where x is the 1402 environment variable name and y is the value. If this 1403 is NULL, then the current shell environment is used. 1404 1405 @param[out] StartImageStatus Returned status from gBS->StartImage. 1415 1406 1416 1407 @retval EFI_SUCCESS The command executed successfully. The status code … … 1427 1418 IN CONST CHAR16 *CommandLine OPTIONAL, 1428 1419 IN CONST CHAR16 **Environment OPTIONAL, 1429 OUT EFI_STATUS *Sta tusCodeOPTIONAL1420 OUT EFI_STATUS *StartImageStatus OPTIONAL 1430 1421 ) 1431 1422 { 1432 1423 EFI_STATUS Status; 1424 EFI_STATUS StartStatus; 1425 EFI_STATUS CleanupStatus; 1433 1426 EFI_HANDLE NewHandle; 1434 1427 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; 1435 1428 LIST_ENTRY OrigEnvs; 1436 1429 EFI_SHELL_PARAMETERS_PROTOCOL ShellParamsProtocol; 1430 CHAR16 *ImagePath; 1431 UINTN Index; 1432 CHAR16 *Walker; 1433 CHAR16 *NewCmdLine; 1437 1434 1438 1435 if (ParentImageHandle == NULL) { … … 1443 1440 1444 1441 NewHandle = NULL; 1442 1443 NewCmdLine = AllocateCopyPool (StrSize (CommandLine), CommandLine); 1444 if (NewCmdLine == NULL) { 1445 return EFI_OUT_OF_RESOURCES; 1446 } 1447 1448 for (Walker = NewCmdLine; Walker != NULL && *Walker != CHAR_NULL ; Walker++) { 1449 if (*Walker == L'^' && *(Walker+1) == L'#') { 1450 CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0])); 1451 } 1452 } 1445 1453 1446 1454 // … … 1472 1480 if (!EFI_ERROR(Status)) { 1473 1481 ASSERT(LoadedImage->LoadOptionsSize == 0); 1474 if ( CommandLine != NULL) {1475 LoadedImage->LoadOptionsSize = (UINT32)StrSize( CommandLine);1476 LoadedImage->LoadOptions = (VOID*) CommandLine;1482 if (NewCmdLine != NULL) { 1483 LoadedImage->LoadOptionsSize = (UINT32)StrSize(NewCmdLine); 1484 LoadedImage->LoadOptions = (VOID*)NewCmdLine; 1477 1485 } 1478 1486 … … 1493 1501 ShellParamsProtocol.StdOut = ShellInfoObject.NewShellParametersProtocol->StdOut; 1494 1502 ShellParamsProtocol.StdErr = ShellInfoObject.NewShellParametersProtocol->StdErr; 1495 Status = UpdateArgcArgv(&ShellParamsProtocol, CommandLine, NULL, NULL);1503 Status = UpdateArgcArgv(&ShellParamsProtocol, NewCmdLine, NULL, NULL); 1496 1504 ASSERT_EFI_ERROR(Status); 1505 // 1506 // Replace Argv[0] with the full path of the binary we're executing: 1507 // If the command line was "foo", the binary might be called "foo.efi". 1508 // "The first entry in [Argv] is always the full file path of the 1509 // executable" - UEFI Shell Spec section 2.3 1510 // 1511 ImagePath = EfiShellGetFilePathFromDevicePath (DevicePath); 1512 // The image we're executing isn't necessarily in a filesystem - it might 1513 // be memory mapped. In this case EfiShellGetFilePathFromDevicePath will 1514 // return NULL, and we'll leave Argv[0] as UpdateArgcArgv set it. 1515 if (ImagePath != NULL) { 1516 if (ShellParamsProtocol.Argv == NULL) { 1517 // Command line was empty or null. 1518 // (UpdateArgcArgv sets Argv to NULL when CommandLine is "" or NULL) 1519 ShellParamsProtocol.Argv = AllocatePool (sizeof (CHAR16 *)); 1520 if (ShellParamsProtocol.Argv == NULL) { 1521 Status = EFI_OUT_OF_RESOURCES; 1522 goto UnloadImage; 1523 } 1524 ShellParamsProtocol.Argc = 1; 1525 } else { 1526 // Free the string UpdateArgcArgv put in Argv[0]; 1527 FreePool (ShellParamsProtocol.Argv[0]); 1528 } 1529 ShellParamsProtocol.Argv[0] = ImagePath; 1530 } 1531 1497 1532 Status = gBS->InstallProtocolInterface(&NewHandle, &gEfiShellParametersProtocolGuid, EFI_NATIVE_INTERFACE, &ShellParamsProtocol); 1498 1533 ASSERT_EFI_ERROR(Status); … … 1504 1539 // 1505 1540 if (!EFI_ERROR(Status)) { 1506 if (StatusCode != NULL) { 1507 *StatusCode = gBS->StartImage(NewHandle, NULL, NULL); 1508 } else { 1509 Status = gBS->StartImage(NewHandle, NULL, NULL); 1541 StartStatus = gBS->StartImage( 1542 NewHandle, 1543 0, 1544 NULL 1545 ); 1546 if (StartImageStatus != NULL) { 1547 *StartImageStatus = StartStatus; 1510 1548 } 1511 } 1512 1513 // 1514 // Cleanup (and dont overwrite errors) 1515 // 1516 if (EFI_ERROR(Status)) { 1517 gBS->UninstallProtocolInterface(NewHandle, &gEfiShellParametersProtocolGuid, &ShellParamsProtocol); 1518 } else { 1519 Status = gBS->UninstallProtocolInterface(NewHandle, &gEfiShellParametersProtocolGuid, &ShellParamsProtocol); 1520 ASSERT_EFI_ERROR(Status); 1521 } 1522 } 1523 1549 1550 CleanupStatus = gBS->UninstallProtocolInterface( 1551 NewHandle, 1552 &gEfiShellParametersProtocolGuid, 1553 &ShellParamsProtocol 1554 ); 1555 ASSERT_EFI_ERROR(CleanupStatus); 1556 1557 goto FreeAlloc; 1558 } 1559 1560 UnloadImage: 1561 // Unload image - We should only get here if we didn't call StartImage 1562 gBS->UnloadImage (NewHandle); 1563 1564 FreeAlloc: 1565 // Free Argv (Allocated in UpdateArgcArgv) 1566 if (ShellParamsProtocol.Argv != NULL) { 1567 for (Index = 0; Index < ShellParamsProtocol.Argc; Index++) { 1568 if (ShellParamsProtocol.Argv[Index] != NULL) { 1569 FreePool (ShellParamsProtocol.Argv[Index]); 1570 } 1571 } 1572 FreePool (ShellParamsProtocol.Argv); 1573 } 1574 } 1575 1576 // Restore environment variables 1524 1577 if (!IsListEmpty(&OrigEnvs)) { 1525 if (EFI_ERROR(Status)) { 1526 SetEnvironmentVariableList(&OrigEnvs); 1527 } else { 1528 Status = SetEnvironmentVariableList(&OrigEnvs); 1529 } 1530 } 1578 CleanupStatus = SetEnvironmentVariableList(&OrigEnvs); 1579 ASSERT_EFI_ERROR (CleanupStatus); 1580 } 1581 1582 FreePool (NewCmdLine); 1531 1583 1532 1584 return(Status); … … 1587 1639 1588 1640 DEBUG_CODE_BEGIN(); 1589 Temp = gDevPathToText->ConvertDevicePathToText(ShellInfoObject.FileDevPath, TRUE, TRUE);1641 Temp = ConvertDevicePathToText(ShellInfoObject.FileDevPath, TRUE, TRUE); 1590 1642 FreePool(Temp); 1591 Temp = gDevPathToText->ConvertDevicePathToText(ShellInfoObject.ImageDevPath, TRUE, TRUE);1643 Temp = ConvertDevicePathToText(ShellInfoObject.ImageDevPath, TRUE, TRUE); 1592 1644 FreePool(Temp); 1593 Temp = gDevPathToText->ConvertDevicePathToText(DevPath, TRUE, TRUE);1645 Temp = ConvertDevicePathToText(DevPath, TRUE, TRUE); 1594 1646 FreePool(Temp); 1595 1647 DEBUG_CODE_END(); … … 1598 1650 Size = 0; 1599 1651 ASSERT((Temp == NULL && Size == 0) || (Temp != NULL)); 1600 StrnCatGrow(&Temp, &Size, L"Shell.efi ", 0);1652 StrnCatGrow(&Temp, &Size, L"Shell.efi -_exit ", 0); 1601 1653 StrnCatGrow(&Temp, &Size, CommandLine, 0); 1602 1654 … … 1675 1727 InternalFreeShellFileInfoNode(ShellFileListItem); 1676 1728 } 1729 InternalFreeShellFileInfoNode(*FileList); 1730 *FileList = NULL; 1677 1731 return(EFI_SUCCESS); 1678 1732 } … … 1696 1750 EFI_SHELL_FILE_INFO *ShellFileListItem; 1697 1751 EFI_SHELL_FILE_INFO *ShellFileListItem2; 1752 EFI_SHELL_FILE_INFO *TempNode; 1698 1753 1699 1754 if (FileList == NULL || *FileList == NULL) { … … 1713 1768 (CHAR16*)ShellFileListItem2->FullName) == 0 1714 1769 ){ 1770 TempNode = (EFI_SHELL_FILE_INFO *)GetPreviousNode( 1771 &(*FileList)->Link, 1772 &ShellFileListItem2->Link 1773 ); 1715 1774 RemoveEntryList(&ShellFileListItem2->Link); 1716 1775 InternalFreeShellFileInfoNode(ShellFileListItem2); 1776 // Set ShellFileListItem2 to PreviousNode so we don't access Freed 1777 // memory in GetNextNode in the loop expression above. 1778 ShellFileListItem2 = TempNode; 1717 1779 } 1718 1780 } … … 1720 1782 return (EFI_SUCCESS); 1721 1783 } 1784 1785 // 1786 // This is the same structure as the external version, but it has no CONST qualifiers. 1787 // 1788 typedef struct { 1789 LIST_ENTRY Link; ///< Linked list members. 1790 EFI_STATUS Status; ///< Status of opening the file. Valid only if Handle != NULL. 1791 CHAR16 *FullName; ///< Fully qualified filename. 1792 CHAR16 *FileName; ///< name of this file. 1793 SHELL_FILE_HANDLE Handle; ///< Handle for interacting with the opened file or NULL if closed. 1794 EFI_FILE_INFO *Info; ///< Pointer to the FileInfo struct for this file or NULL. 1795 } EFI_SHELL_FILE_INFO_NO_CONST; 1796 1722 1797 /** 1723 1798 Allocates and duplicates a EFI_SHELL_FILE_INFO node. … … 1736 1811 ) 1737 1812 { 1738 EFI_SHELL_FILE_INFO *NewNode; 1813 EFI_SHELL_FILE_INFO_NO_CONST *NewNode; 1814 1815 // 1816 // try to confirm that the objects are in sync 1817 // 1818 ASSERT(sizeof(EFI_SHELL_FILE_INFO_NO_CONST) == sizeof(EFI_SHELL_FILE_INFO)); 1739 1819 1740 1820 NewNode = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO)); … … 1742 1822 return (NULL); 1743 1823 } 1744 NewNode->FullName = AllocateZeroPool(StrSize(Node->FullName)); 1745 1746 NewNode->FileName = AllocateZeroPool(StrSize(Node->FileName)); 1747 NewNode->Info = AllocateZeroPool((UINTN)Node->Info->Size); 1824 NewNode->FullName = AllocateCopyPool(StrSize(Node->FullName), Node->FullName); 1825 NewNode->FileName = AllocateCopyPool(StrSize(Node->FileName), Node->FileName); 1826 NewNode->Info = AllocateCopyPool((UINTN)Node->Info->Size, Node->Info); 1748 1827 if ( NewNode->FullName == NULL 1749 1828 || NewNode->FileName == NULL 1750 1829 || NewNode->Info == NULL 1751 ){ 1830 ){ 1831 SHELL_FREE_NON_NULL(NewNode->FullName); 1832 SHELL_FREE_NON_NULL(NewNode->FileName); 1833 SHELL_FREE_NON_NULL(NewNode->Info); 1834 SHELL_FREE_NON_NULL(NewNode); 1752 1835 return(NULL); 1753 1836 } … … 1757 1840 Node->Handle = NULL; 1758 1841 } 1759 StrCpy((CHAR16*)NewNode->FullName, Node->FullName); 1760 StrCpy((CHAR16*)NewNode->FileName, Node->FileName); 1761 CopyMem(NewNode->Info, Node->Info, (UINTN)Node->Info->Size); 1762 1763 return(NewNode); 1842 1843 return((EFI_SHELL_FILE_INFO*)NewNode); 1764 1844 } 1765 1845 … … 1770 1850 @param[in] BasePath the Path to prepend onto filename for FullPath 1771 1851 @param[in] Status Status member initial value. 1772 @param[in] FullName FullName member initial value.1773 1852 @param[in] FileName FileName member initial value. 1774 1853 @param[in] Handle Handle member initial value. … … 1783 1862 IN CONST CHAR16 *BasePath, 1784 1863 IN CONST EFI_STATUS Status, 1785 IN CONST CHAR16 *FullName,1786 1864 IN CONST CHAR16 *FileName, 1787 1865 IN CONST SHELL_FILE_HANDLE Handle, … … 1800 1878 return (NULL); 1801 1879 } 1802 if (Info != NULL ) {1880 if (Info != NULL && Info->Size != 0) { 1803 1881 ShellFileListItem->Info = AllocateZeroPool((UINTN)Info->Size); 1804 1882 if (ShellFileListItem->Info == NULL) { … … 1828 1906 if (TempString == NULL) { 1829 1907 FreePool((VOID*)ShellFileListItem->FileName); 1830 FreePool(ShellFileListItem->Info);1908 SHELL_FREE_NON_NULL(ShellFileListItem->Info); 1831 1909 FreePool(ShellFileListItem); 1832 1910 return (NULL); … … 1843 1921 } 1844 1922 } 1923 1924 TempString = PathCleanUpDirectories(TempString); 1845 1925 1846 1926 ShellFileListItem->FullName = TempString; … … 1882 1962 CHAR16 *TempSpot; 1883 1963 1964 BasePath = NULL; 1884 1965 Status = FileHandleGetFileName(FileDirHandle, &BasePath); 1885 1966 if (EFI_ERROR(Status)) { … … 1892 1973 TempString = StrnCatGrow(&TempString, &Size, ShellFileHandleGetPath(FileDirHandle), 0); 1893 1974 if (TempString == NULL) { 1975 SHELL_FREE_NON_NULL(BasePath); 1894 1976 return (EFI_OUT_OF_RESOURCES); 1895 1977 } … … 1902 1984 TempString = StrnCatGrow(&TempString, &Size, BasePath, 0); 1903 1985 if (TempString == NULL) { 1986 SHELL_FREE_NON_NULL(BasePath); 1904 1987 return (EFI_OUT_OF_RESOURCES); 1905 1988 } 1989 SHELL_FREE_NON_NULL(BasePath); 1906 1990 BasePath = TempString; 1907 1991 } … … 1918 2002 ; Status = FileHandleFindNextFile(FileDirHandle, FileInfo, &NoFile) 1919 2003 ){ 1920 TempString = NULL;1921 Size = 0;1922 2004 // 1923 2005 // allocate a new EFI_SHELL_FILE_INFO and populate it... 1924 2006 // 1925 ASSERT((TempString == NULL && Size == 0) || (TempString != NULL));1926 TempString = StrnCatGrow(&TempString, &Size, BasePath, 0);1927 TempString = StrnCatGrow(&TempString, &Size, FileInfo->FileName, 0);1928 2007 ShellFileListItem = CreateAndPopulateShellFileInfo( 1929 2008 BasePath, 1930 EFI_SUCCESS, // success since we didnt fail to open it... 1931 TempString, 2009 EFI_SUCCESS, // success since we didnt fail to open it... 1932 2010 FileInfo->FileName, 1933 NULL, // no handle since not open2011 NULL, // no handle since not open 1934 2012 FileInfo); 1935 2013 … … 1949 2027 SHELL_FREE_NON_NULL(BasePath); 1950 2028 return(Status); 2029 } 2030 2031 /** 2032 Get the GUID value from a human readable name. 2033 2034 If GuidName is a known GUID name, then update Guid to have the correct value for 2035 that GUID. 2036 2037 This function is only available when the major and minor versions in the 2038 EfiShellProtocol are greater than or equal to 2 and 1, respectively. 2039 2040 @param[in] GuidName A pointer to the localized name for the GUID being queried. 2041 @param[out] Guid A pointer to the GUID structure to be filled in. 2042 2043 @retval EFI_SUCCESS The operation was successful. 2044 @retval EFI_INVALID_PARAMETER Guid was NULL. 2045 @retval EFI_INVALID_PARAMETER GuidName was NULL. 2046 @retval EFI_NOT_FOUND GuidName is not a known GUID Name. 2047 **/ 2048 EFI_STATUS 2049 EFIAPI 2050 EfiShellGetGuidFromName( 2051 IN CONST CHAR16 *GuidName, 2052 OUT EFI_GUID *Guid 2053 ) 2054 { 2055 EFI_GUID *NewGuid; 2056 EFI_STATUS Status; 2057 2058 if (Guid == NULL || GuidName == NULL) { 2059 return (EFI_INVALID_PARAMETER); 2060 } 2061 2062 Status = GetGuidFromStringName(GuidName, NULL, &NewGuid); 2063 2064 if (!EFI_ERROR(Status)) { 2065 CopyGuid(NewGuid, Guid); 2066 } 2067 2068 return (Status); 2069 } 2070 2071 /** 2072 Get the human readable name for a GUID from the value. 2073 2074 If Guid is assigned a name, then update *GuidName to point to the name. The callee 2075 should not modify the value. 2076 2077 This function is only available when the major and minor versions in the 2078 EfiShellProtocol are greater than or equal to 2 and 1, respectively. 2079 2080 @param[in] Guid A pointer to the GUID being queried. 2081 @param[out] GuidName A pointer to a pointer the localized to name for the GUID being requested 2082 2083 @retval EFI_SUCCESS The operation was successful. 2084 @retval EFI_INVALID_PARAMETER Guid was NULL. 2085 @retval EFI_INVALID_PARAMETER GuidName was NULL. 2086 @retval EFI_NOT_FOUND Guid is not assigned a name. 2087 **/ 2088 EFI_STATUS 2089 EFIAPI 2090 EfiShellGetGuidName( 2091 IN CONST EFI_GUID *Guid, 2092 OUT CONST CHAR16 **GuidName 2093 ) 2094 { 2095 CHAR16 *Name; 2096 2097 if (Guid == NULL || GuidName == NULL) { 2098 return (EFI_INVALID_PARAMETER); 2099 } 2100 2101 Name = GetStringNameFromGuid(Guid, NULL); 2102 if (Name == NULL || StrLen(Name) == 0) { 2103 SHELL_FREE_NON_NULL(Name); 2104 return (EFI_NOT_FOUND); 2105 } 2106 2107 *GuidName = AddBufferToFreeList(Name); 2108 2109 return (EFI_SUCCESS); 1951 2110 } 1952 2111 … … 2038 2197 EFI_SHELL_FILE_INFO *ShellInfoNode; 2039 2198 EFI_SHELL_FILE_INFO *NewShellNode; 2199 EFI_FILE_INFO *FileInfo; 2040 2200 BOOLEAN Directory; 2041 2201 CHAR16 *NewFullName; … … 2065 2225 if (CurrentFilePattern[0] == CHAR_NULL 2066 2226 &&NextFilePatternStart[0] == CHAR_NULL 2067 ){2068 // 2069 // Add the current parameter FileHandle to the list, then end...2227 ){ 2228 // 2229 // we want the parent or root node (if no parent) 2070 2230 // 2071 2231 if (ParentNode == NULL) { 2072 Status = EFI_INVALID_PARAMETER; 2232 // 2233 // We want the root node. create the node. 2234 // 2235 FileInfo = FileHandleGetInfo(FileHandle); 2236 NewShellNode = CreateAndPopulateShellFileInfo( 2237 MapName, 2238 EFI_SUCCESS, 2239 L"\\", 2240 FileHandle, 2241 FileInfo 2242 ); 2243 SHELL_FREE_NON_NULL(FileInfo); 2073 2244 } else { 2245 // 2246 // Add the current parameter FileHandle to the list, then end... 2247 // 2074 2248 NewShellNode = InternalDuplicateShellFileInfo((EFI_SHELL_FILE_INFO*)ParentNode, TRUE); 2075 if (NewShellNode == NULL) { 2076 Status = EFI_OUT_OF_RESOURCES; 2077 } else { 2078 NewShellNode->Handle = NULL; 2079 if (*FileList == NULL) { 2080 *FileList = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO)); 2081 InitializeListHead(&((*FileList)->Link)); 2082 } 2083 2084 // 2085 // Add to the returning to use list 2086 // 2087 InsertTailList(&(*FileList)->Link, &NewShellNode->Link); 2088 2089 Status = EFI_SUCCESS; 2249 } 2250 if (NewShellNode == NULL) { 2251 Status = EFI_OUT_OF_RESOURCES; 2252 } else { 2253 NewShellNode->Handle = NULL; 2254 if (*FileList == NULL) { 2255 *FileList = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO)); 2256 InitializeListHead(&((*FileList)->Link)); 2090 2257 } 2258 2259 // 2260 // Add to the returning to use list 2261 // 2262 InsertTailList(&(*FileList)->Link, &NewShellNode->Link); 2263 2264 Status = EFI_SUCCESS; 2091 2265 } 2092 2266 } else { … … 2111 2285 Status = EFI_OUT_OF_RESOURCES; 2112 2286 } else { 2113 Str Cpy(NewFullName, MapName);2114 Str Cat(NewFullName, ShellInfoNode->FullName+1);2287 StrnCpy(NewFullName, MapName, Size/sizeof(CHAR16)-1); 2288 StrnCat(NewFullName, ShellInfoNode->FullName+1, (Size/sizeof(CHAR16))-StrLen(NewFullName)-1); 2115 2289 FreePool((VOID*)ShellInfoNode->FullName); 2116 2290 ShellInfoNode->FullName = NewFullName; … … 2235 2409 RootFileHandle = NULL; 2236 2410 MapName = NULL; 2237 PatternCopy = Allocate ZeroPool(StrSize(FilePattern));2411 PatternCopy = AllocateCopyPool(StrSize(FilePattern), FilePattern); 2238 2412 if (PatternCopy == NULL) { 2239 2413 return (EFI_OUT_OF_RESOURCES); 2240 2414 } 2241 StrCpy(PatternCopy, FilePattern);2242 2415 2243 2416 PatternCopy = PathCleanUpDirectories(PatternCopy); … … 2368 2541 2369 2542 /** 2370 This function updated with errata. 2371 2543 Gets the environment variable and Attributes, or list of environment variables. Can be 2544 used instead of GetEnv(). 2545 2546 This function returns the current value of the specified environment variable and 2547 the Attributes. If no variable name was specified, then all of the known 2548 variables will be returned. 2549 2550 @param[in] Name A pointer to the environment variable name. If Name is NULL, 2551 then the function will return all of the defined shell 2552 environment variables. In the case where multiple environment 2553 variables are being returned, each variable will be terminated 2554 by a NULL, and the list will be terminated by a double NULL. 2555 @param[out] Attributes If not NULL, a pointer to the returned attributes bitmask for 2556 the environment variable. In the case where Name is NULL, and 2557 multiple environment variables are being returned, Attributes 2558 is undefined. 2559 2560 @retval NULL The environment variable doesn't exist. 2561 @return A non-NULL value points to the variable's value. The returned 2562 pointer does not need to be freed by the caller. 2563 **/ 2564 CONST CHAR16 * 2565 EFIAPI 2566 EfiShellGetEnvEx( 2567 IN CONST CHAR16 *Name, 2568 OUT UINT32 *Attributes OPTIONAL 2569 ) 2570 { 2571 EFI_STATUS Status; 2572 VOID *Buffer; 2573 UINTN Size; 2574 LIST_ENTRY List; 2575 ENV_VAR_LIST *Node; 2576 CHAR16 *CurrentWriteLocation; 2577 2578 Size = 0; 2579 Buffer = NULL; 2580 2581 if (Name == NULL) { 2582 // 2583 // Get all our environment variables 2584 // 2585 InitializeListHead(&List); 2586 Status = GetEnvironmentVariableList(&List); 2587 if (EFI_ERROR(Status)){ 2588 return (NULL); 2589 } 2590 2591 // 2592 // Build the semi-colon delimited list. (2 passes) 2593 // 2594 for ( Node = (ENV_VAR_LIST*)GetFirstNode(&List) 2595 ; !IsNull(&List, &Node->Link) 2596 ; Node = (ENV_VAR_LIST*)GetNextNode(&List, &Node->Link) 2597 ){ 2598 ASSERT(Node->Key != NULL); 2599 Size += StrSize(Node->Key); 2600 } 2601 2602 Size += 2*sizeof(CHAR16); 2603 2604 Buffer = AllocateZeroPool(Size); 2605 if (Buffer == NULL) { 2606 if (!IsListEmpty (&List)) { 2607 FreeEnvironmentVariableList(&List); 2608 } 2609 return (NULL); 2610 } 2611 CurrentWriteLocation = (CHAR16*)Buffer; 2612 2613 for ( Node = (ENV_VAR_LIST*)GetFirstNode(&List) 2614 ; !IsNull(&List, &Node->Link) 2615 ; Node = (ENV_VAR_LIST*)GetNextNode(&List, &Node->Link) 2616 ){ 2617 ASSERT(Node->Key != NULL); 2618 StrnCpy(CurrentWriteLocation, Node->Key, (Size)/sizeof(CHAR16) - (CurrentWriteLocation - ((CHAR16*)Buffer)) - 1); 2619 CurrentWriteLocation += StrLen(CurrentWriteLocation) + 1; 2620 } 2621 2622 // 2623 // Free the list... 2624 // 2625 if (!IsListEmpty (&List)) { 2626 FreeEnvironmentVariableList(&List); 2627 } 2628 } else { 2629 // 2630 // We are doing a specific environment variable 2631 // 2632 2633 // 2634 // get the size we need for this EnvVariable 2635 // 2636 Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(Name, Attributes, &Size, Buffer); 2637 if (Status == EFI_BUFFER_TOO_SMALL) { 2638 // 2639 // Allocate the space and recall the get function 2640 // 2641 Buffer = AllocateZeroPool(Size); 2642 Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(Name, Attributes, &Size, Buffer); 2643 } 2644 // 2645 // we didnt get it (might not exist) 2646 // free the memory if we allocated any and return NULL 2647 // 2648 if (EFI_ERROR(Status)) { 2649 if (Buffer != NULL) { 2650 FreePool(Buffer); 2651 } 2652 return (NULL); 2653 } 2654 } 2655 2656 // 2657 // return the buffer 2658 // 2659 return (AddBufferToFreeList(Buffer)); 2660 } 2661 2662 /** 2372 2663 Gets either a single or list of environment variables. 2373 2664 … … 2386 2677 NULL. 2387 2678 2388 @ret urn!=NULL A pointer to the returned string.2679 @retval !=NULL A pointer to the returned string. 2389 2680 The returned pointer does not need to be freed by the caller. 2390 2681 … … 2398 2689 ) 2399 2690 { 2400 EFI_STATUS Status; 2401 VOID *Buffer; 2402 UINTN Size; 2403 LIST_ENTRY List; 2404 ENV_VAR_LIST *Node; 2405 CHAR16 *CurrentWriteLocation; 2406 2407 Size = 0; 2408 Buffer = NULL; 2409 2410 if (Name == NULL) { 2411 // 2412 // Get all our environment variables 2413 // 2414 InitializeListHead(&List); 2415 Status = GetEnvironmentVariableList(&List); 2416 if (EFI_ERROR(Status)){ 2417 return (NULL); 2418 } 2419 2420 // 2421 // Build the semi-colon delimited list. (2 passes) 2422 // 2423 for ( Node = (ENV_VAR_LIST*)GetFirstNode(&List) 2424 ; !IsNull(&List, &Node->Link) 2425 ; Node = (ENV_VAR_LIST*)GetNextNode(&List, &Node->Link) 2426 ){ 2427 ASSERT(Node->Key != NULL); 2428 Size += StrSize(Node->Key); 2429 } 2430 2431 Size += 2*sizeof(CHAR16); 2432 2433 Buffer = AllocateZeroPool(Size); 2434 if (Buffer == NULL) { 2435 if (!IsListEmpty (&List)) { 2436 FreeEnvironmentVariableList(&List); 2437 } 2438 return (NULL); 2439 } 2440 CurrentWriteLocation = (CHAR16*)Buffer; 2441 2442 for ( Node = (ENV_VAR_LIST*)GetFirstNode(&List) 2443 ; !IsNull(&List, &Node->Link) 2444 ; Node = (ENV_VAR_LIST*)GetNextNode(&List, &Node->Link) 2445 ){ 2446 ASSERT(Node->Key != NULL); 2447 StrCpy(CurrentWriteLocation, Node->Key); 2448 CurrentWriteLocation += StrLen(CurrentWriteLocation) + 1; 2449 } 2450 2451 // 2452 // Free the list... 2453 // 2454 if (!IsListEmpty (&List)) { 2455 FreeEnvironmentVariableList(&List); 2456 } 2457 } else { 2458 // 2459 // We are doing a specific environment variable 2460 // 2461 2462 // 2463 // get the size we need for this EnvVariable 2464 // 2465 Status = SHELL_GET_ENVIRONMENT_VARIABLE(Name, &Size, Buffer); 2466 if (Status == EFI_BUFFER_TOO_SMALL) { 2467 // 2468 // Allocate the space and recall the get function 2469 // 2470 Buffer = AllocateZeroPool(Size); 2471 ASSERT(Buffer != NULL); 2472 Status = SHELL_GET_ENVIRONMENT_VARIABLE(Name, &Size, Buffer); 2473 } 2474 // 2475 // we didnt get it (might not exist) 2476 // free the memory if we allocated any and return NULL 2477 // 2478 if (EFI_ERROR(Status)) { 2479 if (Buffer != NULL) { 2480 FreePool(Buffer); 2481 } 2482 return (NULL); 2483 } 2484 } 2485 2486 // 2487 // return the buffer 2488 // 2489 return (AddBufferToFreeList(Buffer)); 2691 return (EfiShellGetEnvEx(Name, NULL)); 2490 2692 } 2491 2693 … … 2825 3027 { 2826 3028 CONST CHAR16 *ManFileName; 3029 CHAR16 *FixCommand; 3030 EFI_STATUS Status; 2827 3031 2828 3032 ASSERT(HelpText != NULL); 3033 FixCommand = NULL; 2829 3034 2830 3035 ManFileName = ShellCommandGetManFileNameHandler(Command); … … 2833 3038 return (ProcessManFile(ManFileName, Command, Sections, NULL, HelpText)); 2834 3039 } else { 2835 return (ProcessManFile(Command, Command, Sections, NULL, HelpText)); 3040 if ((StrLen(Command)> 4) 3041 && (Command[StrLen(Command)-1] == L'i' || Command[StrLen(Command)-1] == L'I') 3042 && (Command[StrLen(Command)-2] == L'f' || Command[StrLen(Command)-2] == L'F') 3043 && (Command[StrLen(Command)-3] == L'e' || Command[StrLen(Command)-3] == L'E') 3044 && (Command[StrLen(Command)-4] == L'.') 3045 ) { 3046 FixCommand = AllocateZeroPool(StrSize(Command) - 4 * sizeof (CHAR16)); 3047 ASSERT(FixCommand != NULL); 3048 3049 StrnCpy(FixCommand, Command, StrLen(Command)-4); 3050 Status = ProcessManFile(FixCommand, FixCommand, Sections, NULL, HelpText); 3051 FreePool(FixCommand); 3052 return Status; 3053 } else { 3054 return (ProcessManFile(Command, Command, Sections, NULL, HelpText)); 3055 } 2836 3056 } 2837 3057 } … … 2885 3105 ) 2886 3106 { 2887 UINT64 MaxStorSize; 2888 UINT64 RemStorSize; 2889 UINT64 MaxVarSize; 3107 2890 3108 EFI_STATUS Status; 2891 3109 EFI_GUID Guid; 2892 3110 CHAR16 *VariableName; 2893 3111 UINTN NameSize; 3112 UINTN NameBufferSize; 2894 3113 CHAR16 *RetVal; 2895 3114 UINTN RetSize; 2896 CHAR16 *Alias; 2897 2898 Status = gRT->QueryVariableInfo(EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS, &MaxStorSize, &RemStorSize, &MaxVarSize); 2899 ASSERT_EFI_ERROR(Status); 2900 2901 VariableName = AllocateZeroPool((UINTN)MaxVarSize); 3115 3116 NameBufferSize = INIT_NAME_BUFFER_SIZE; 3117 VariableName = AllocateZeroPool(NameBufferSize); 2902 3118 RetSize = 0; 2903 3119 RetVal = NULL; … … 2910 3126 2911 3127 while (TRUE) { 2912 NameSize = (UINTN)MaxVarSize;3128 NameSize = NameBufferSize; 2913 3129 Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid); 2914 3130 if (Status == EFI_NOT_FOUND){ 2915 3131 break; 2916 } 2917 ASSERT_EFI_ERROR(Status); 2918 if (EFI_ERROR(Status)) { 3132 } else if (Status == EFI_BUFFER_TOO_SMALL) { 3133 NameBufferSize = NameSize > NameBufferSize * 2 ? NameSize : NameBufferSize * 2; 3134 SHELL_FREE_NON_NULL(VariableName); 3135 VariableName = AllocateZeroPool(NameBufferSize); 3136 if (VariableName == NULL) { 3137 Status = EFI_OUT_OF_RESOURCES; 3138 SHELL_FREE_NON_NULL(RetVal); 3139 RetVal = NULL; 3140 break; 3141 } 3142 3143 NameSize = NameBufferSize; 3144 Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid); 3145 } 3146 3147 if (EFI_ERROR (Status)) { 3148 SHELL_FREE_NON_NULL(RetVal); 3149 RetVal = NULL; 2919 3150 break; 2920 3151 } 3152 2921 3153 if (CompareGuid(&Guid, &gShellAliasGuid)){ 2922 Alias = GetVariable(VariableName, &gShellAliasGuid);2923 3154 ASSERT((RetVal == NULL && RetSize == 0) || (RetVal != NULL)); 2924 3155 RetVal = StrnCatGrow(&RetVal, &RetSize, VariableName, 0); … … 2926 3157 } // compare guid 2927 3158 } // while 2928 FreePool(VariableName);3159 SHELL_FREE_NON_NULL(VariableName); 2929 3160 2930 3161 return (RetVal); 3162 } 3163 3164 /** 3165 Convert a null-terminated unicode string, in-place, to all lowercase. 3166 Then return it. 3167 3168 @param Str The null-terminated string to be converted to all lowercase. 3169 3170 @return The null-terminated string converted into all lowercase. 3171 **/ 3172 CHAR16 * 3173 ToLower ( 3174 CHAR16 *Str 3175 ) 3176 { 3177 UINTN Index; 3178 3179 for (Index = 0; Str[Index] != L'\0'; Index++) { 3180 if (Str[Index] >= L'A' && Str[Index] <= L'Z') { 3181 Str[Index] -= (CHAR16)(L'A' - L'a'); 3182 } 3183 } 3184 return Str; 2931 3185 } 2932 3186 … … 2960 3214 UINT32 Attribs; 2961 3215 EFI_STATUS Status; 2962 3216 CHAR16 *AliasLower; 3217 3218 // Convert to lowercase to make aliases case-insensitive 2963 3219 if (Alias != NULL) { 3220 AliasLower = AllocateCopyPool (StrSize (Alias), Alias); 3221 ASSERT (AliasLower != NULL); 3222 ToLower (AliasLower); 3223 2964 3224 if (Volatile == NULL) { 2965 return (AddBufferToFreeList(GetVariable( (CHAR16*)Alias, &gShellAliasGuid)));3225 return (AddBufferToFreeList(GetVariable(AliasLower, &gShellAliasGuid))); 2966 3226 } 2967 3227 RetSize = 0; 2968 3228 RetVal = NULL; 2969 Status = gRT->GetVariable( (CHAR16*)Alias, &gShellAliasGuid, &Attribs, &RetSize, RetVal);3229 Status = gRT->GetVariable(AliasLower, &gShellAliasGuid, &Attribs, &RetSize, RetVal); 2970 3230 if (Status == EFI_BUFFER_TOO_SMALL) { 2971 3231 RetVal = AllocateZeroPool(RetSize); 2972 Status = gRT->GetVariable( (CHAR16*)Alias, &gShellAliasGuid, &Attribs, &RetSize, RetVal);3232 Status = gRT->GetVariable(AliasLower, &gShellAliasGuid, &Attribs, &RetSize, RetVal); 2973 3233 } 2974 3234 if (EFI_ERROR(Status)) { … … 2984 3244 } 2985 3245 3246 FreePool (AliasLower); 2986 3247 return (AddBufferToFreeList(RetVal)); 2987 3248 } … … 3013 3274 ) 3014 3275 { 3276 EFI_STATUS Status; 3277 CHAR16 *AliasLower; 3278 3279 // Convert to lowercase to make aliases case-insensitive 3280 if (Alias != NULL) { 3281 AliasLower = AllocateCopyPool (StrSize (Alias), Alias); 3282 ASSERT (AliasLower != NULL); 3283 ToLower (AliasLower); 3284 } else { 3285 AliasLower = NULL; 3286 } 3287 3015 3288 // 3016 3289 // We must be trying to remove one if Alias is NULL … … 3020 3293 // remove an alias (but passed in COMMAND parameter) 3021 3294 // 3022 return(gRT->SetVariable((CHAR16*)Command, &gShellAliasGuid, 0, 0, NULL));3295 Status = (gRT->SetVariable((CHAR16*)Command, &gShellAliasGuid, 0, 0, NULL)); 3023 3296 } else { 3024 3297 // … … 3029 3302 gRT->SetVariable((CHAR16*)Command, &gShellAliasGuid, 0, 0, NULL); 3030 3303 3031 return (gRT->SetVariable((CHAR16*)Alias, &gShellAliasGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS|(Volatile?0:EFI_VARIABLE_NON_VOLATILE), StrSize(Command), (VOID*)Command)); 3032 } 3304 Status = (gRT->SetVariable((CHAR16*)Alias, &gShellAliasGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS|(Volatile?0:EFI_VARIABLE_NON_VOLATILE), StrSize(Command), (VOID*)Command)); 3305 } 3306 3307 if (Alias != NULL) { 3308 FreePool (AliasLower); 3309 } 3310 return Status; 3033 3311 } 3034 3312 … … 3052 3330 @retval EFI_ACCESS_DENIED The alias is a built-in alias or already existed and Replace was set to 3053 3331 FALSE. 3332 @retval EFI_INVALID_PARAMETER Command is null or the empty string. 3054 3333 **/ 3055 3334 EFI_STATUS … … 3062 3341 ) 3063 3342 { 3064 //3065 // cant set over a built in alias3066 //3067 3343 if (ShellCommandIsOnAliasList(Alias==NULL?Command:Alias)) { 3344 // 3345 // cant set over a built in alias 3346 // 3068 3347 return (EFI_ACCESS_DENIED); 3069 } 3070 if (Command == NULL || *Command == CHAR_NULL || StrLen(Command) == 0) { 3348 } else if (Command == NULL || *Command == CHAR_NULL || StrLen(Command) == 0) { 3349 // 3350 // Command is null or empty 3351 // 3071 3352 return (EFI_INVALID_PARAMETER); 3072 } 3073 3074 if (EfiShellGetAlias(Command, NULL) != NULL && !Replace) { 3353 } else if (EfiShellGetAlias(Command, NULL) != NULL && !Replace) { 3354 // 3355 // Alias already exists, Replace not set 3356 // 3075 3357 return (EFI_ACCESS_DENIED); 3076 } 3077 3078 return (InternalSetAlias(Command, Alias, Volatile));3358 } else { 3359 return (InternalSetAlias(Command, Alias, Volatile)); 3360 } 3079 3361 } 3080 3362 … … 3123 3405 NULL, 3124 3406 SHELL_MAJOR_VERSION, 3125 SHELL_MINOR_VERSION 3407 SHELL_MINOR_VERSION, 3408 3409 // New for UEFI Shell 2.1 3410 EfiShellRegisterGuidName, 3411 EfiShellGetGuidName, 3412 EfiShellGetGuidFromName, 3413 EfiShellGetEnvEx 3126 3414 }; 3127 3415 … … 3337 3625 ) 3338 3626 { 3339 // ShellPrintEx(-1,-1,L" <Notify> "); 3340 if ((KeyData->Key.UnicodeChar == L'c' || KeyData->Key.UnicodeChar == 3) &&3341 (KeyData->Key State.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED) || KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED))3627 if ( ((KeyData->Key.UnicodeChar == L'c') && 3628 (KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED) || KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED))) || 3629 (KeyData->Key.UnicodeChar == 3) 3342 3630 ){ 3343 3631 if (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak == NULL) { … … 3429 3717 return (Status); 3430 3718 } 3719 -
trunk/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/Shell/ShellProtocol.h
r48674 r58459 3 3 manipulation, and initialization of EFI_SHELL_PROTOCOL. 4 4 5 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR> 5 (C) Copyright 2014, Hewlett-Packard Development Company, L.P. 6 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR> 6 7 This program and the accompanying materials 7 8 are licensed and made available under the terms and conditions of the BSD License … … 17 18 #define _SHELL_PROTOCOL_HEADER_ 18 19 19 #include <Uefi.h> 20 #include <ShellBase.h> 21 22 #include <Guid/ShellVariableGuid.h> 23 #include <Guid/ShellMapGuid.h> 24 #include <Guid/ShellAliasGuid.h> 25 26 #include <Protocol/EfiShell.h> 27 #include <Protocol/EfiShellParameters.h> 28 #include <Protocol/SimpleFileSystem.h> 29 #include <Protocol/DevicePathToText.h> 30 #include <Protocol/ComponentName2.h> 31 #include <Protocol/LoadedImage.h> 32 #include <Protocol/UnicodeCollation.h> 33 #include <Protocol/DevicePath.h> 34 #include <Protocol/SimpleTextInEx.h> 35 36 #include <Library/UefiBootServicesTableLib.h> 37 #include <Library/BaseLib.h> 38 #include <Library/ShellCommandLib.h> 39 #include <Library/PrintLib.h> 40 #include <Library/DevicePathLib.h> 41 #include <Library/UefiRuntimeServicesTableLib.h> 42 #include <Library/DebugLib.h> 43 #include <Library/MemoryAllocationLib.h> 44 #include <Library/BaseMemoryLib.h> 45 #include <Library/UefiLib.h> 46 #include <Library/SortLib.h> 47 #include <Library/PcdLib.h> 48 #include <Library/ShellLib.h> 49 50 #include "FileHandleWrappers.h" 51 #include "ShellEnvVar.h" 52 #include "ShellManParser.h" 20 #include "Shell.h" 53 21 54 22 typedef struct { … … 467 435 internal worker function to run a command via Device Path 468 436 469 @param ParentImageHandle A handle of the image that is executing the specified470 command line.471 @param DevicePath device path of the file to execute472 @param CommandLine Points to the NULL-terminated UCS-2 encoded string473 containing the command line. If NULL then the command-474 line will be empty.475 @param Environment Points to a NULL-terminated array of environment476 variables with the format 'x=y', where x is the477 environment variable name and y is the value. If this478 is NULL, then the current shell environment is used.479 @param StatusCode Points to the status code returned by the command.437 @param ParentImageHandle A handle of the image that is executing the specified 438 command line. 439 @param DevicePath device path of the file to execute 440 @param CommandLine Points to the NULL-terminated UCS-2 encoded string 441 containing the command line. If NULL then the command- 442 line will be empty. 443 @param Environment Points to a NULL-terminated array of environment 444 variables with the format 'x=y', where x is the 445 environment variable name and y is the value. If this 446 is NULL, then the current shell environment is used. 447 @param[out] StartImageStatus Returned status from gBS->StartImage. 480 448 481 449 @retval EFI_SUCCESS The command executed successfully. The status code … … 488 456 EFIAPI 489 457 InternalShellExecuteDevicePath( 490 IN CONST EFI_HANDLE *ParentImageHandle,458 IN CONST EFI_HANDLE *ParentImageHandle, 491 459 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, 492 IN CONST CHAR16 *CommandLine OPTIONAL,493 IN CONST CHAR16 **Environment OPTIONAL,494 OUT EFI_STATUS *StatusCodeOPTIONAL460 IN CONST CHAR16 *CommandLine OPTIONAL, 461 IN CONST CHAR16 **Environment OPTIONAL, 462 OUT EFI_STATUS *StartImageStatus OPTIONAL 495 463 ); 496 464 … … 589 557 @param[in] BasePath the Path to prepend onto filename for FullPath 590 558 @param[in] Status Status member initial value. 591 @param[in] FullName FullName member initial value.592 559 @param[in] FileName FileName member initial value. 593 560 @param[in] Handle Handle member initial value. … … 600 567 IN CONST CHAR16 *BasePath, 601 568 IN CONST EFI_STATUS Status, 602 IN CONST CHAR16 *FullName,603 569 IN CONST CHAR16 *FileName, 604 570 IN CONST SHELL_FILE_HANDLE Handle, … … 689 655 @param Name A pointer to the environment variable name 690 656 691 @ret urn!=NULL The environment variable's value. The returned657 @retval !=NULL The environment variable's value. The returned 692 658 pointer does not need to be freed by the caller. 693 659 @retval NULL The environment variable doesn't exist.
Note:
See TracChangeset
for help on using the changeset viewer.