Very nice. I like this much more. Reviewed-by: Jaben Carsey <jaben.car...@intel.com>
Ray, what do you think? -Jaben > -----Original Message----- > From: Qiu, Shumin > Sent: Wednesday, June 22, 2016 1:51 AM > To: edk2-devel@lists.01.org > Cc: Qiu, Shumin <shumin....@intel.com>; Carsey, Jaben > <jaben.car...@intel.com>; Ni, Ruiyu <ruiyu...@intel.com> > Subject: [PATCH v2] ShellPkg: Fix 'echo' cannot display the special characters > correctly. > Importance: High > > Difference with previous: > Use Shell command Lib API to get original command string. > > Currently run 'echo -t' will get the result: > echo: Unknown flag - '-t' > The expected result is to display '-t' literally. > This patch adds special handle for 'echo'. 'echo' will not use the > general parameter parsing library . > > Cc: Jaben Carsey <jaben.car...@intel.com> > Cc: Ruiyu Ni <ruiyu...@intel.com> > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Qiu Shumin <shumin....@intel.com> > --- > ShellPkg/Application/Shell/Shell.c | 63 ++-- > ShellPkg/Application/Shell/Shell.h | 18 -- > .../Application/Shell/ShellParametersProtocol.c | 156 --------- > .../Application/Shell/ShellParametersProtocol.h | 29 -- > ShellPkg/Include/Library/ShellCommandLib.h | 120 +++++-- > .../UefiShellCommandLib/UefiShellCommandLib.c | 360 > +++++++++++++++++---- > ShellPkg/Library/UefiShellLevel3CommandsLib/Echo.c | 145 ++++----- > .../UefiShellLevel3CommandsLib.uni | 1 + > 8 files changed, 490 insertions(+), 402 deletions(-) > > diff --git a/ShellPkg/Application/Shell/Shell.c > b/ShellPkg/Application/Shell/Shell.c > index 54ca76a..90d6903 100644 > --- a/ShellPkg/Application/Shell/Shell.c > +++ b/ShellPkg/Application/Shell/Shell.c > @@ -716,6 +716,7 @@ FreeResources: > } > > ShellFreeEnvVarList (); > + ShellSetOriginalCmdLine (NULL); > > if (ShellCommandGetExit()) { > return ((EFI_STATUS)ShellCommandGetExitCode()); > @@ -2578,6 +2579,7 @@ RunShellCommand( > CHAR16 *FirstParameter; > CHAR16 *TempWalker; > SHELL_OPERATION_TYPES Type; > + CHAR16 *OldCmdLine; > > ASSERT(CmdLine != NULL); > if (StrLen(CmdLine) == 0) { > @@ -2585,11 +2587,14 @@ RunShellCommand( > } > > Status = EFI_SUCCESS; > + FirstParameter = NULL; > CleanOriginal = NULL; > + OldCmdLine = NULL; > > CleanOriginal = StrnCatGrow(&CleanOriginal, NULL, CmdLine, 0); > if (CleanOriginal == NULL) { > - return (EFI_OUT_OF_RESOURCES); > + Status = EFI_OUT_OF_RESOURCES; > + goto Done; > } > > TrimSpaces(&CleanOriginal); > @@ -2616,23 +2621,24 @@ RunShellCommand( > // Handle case that passed in command line is just 1 or more " " > characters. > // > if (StrLen (CleanOriginal) == 0) { > - SHELL_FREE_NON_NULL(CleanOriginal); > - return (EFI_SUCCESS); > + Status = EFI_SUCCESS; > + goto Done; > } > > Status = ProcessCommandLineToFinal(&CleanOriginal); > if (EFI_ERROR(Status)) { > - SHELL_FREE_NON_NULL(CleanOriginal); > - return (Status); > + goto Done; > } > + > + OldCmdLine = ShellGetOriginalCmdLine(); > + ShellSetOriginalCmdLine(CleanOriginal); > > // > // We don't do normal processing with a split command line (output from > one command input to another) > // > if (ContainsSplit(CleanOriginal)) { > Status = ProcessNewSplitCommandLine(CleanOriginal); > - SHELL_FREE_NON_NULL(CleanOriginal); > - return (Status); > + goto Done; > } > > // > @@ -2640,8 +2646,8 @@ RunShellCommand( > // > FirstParameter = AllocateZeroPool(StrSize(CleanOriginal)); > if (FirstParameter == NULL) { > - SHELL_FREE_NON_NULL(CleanOriginal); > - return (EFI_OUT_OF_RESOURCES); > + Status = EFI_OUT_OF_RESOURCES; > + goto Done; > } > TempWalker = CleanOriginal; > if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, > StrSize(CleanOriginal), TRUE))) { > @@ -2669,7 +2675,10 @@ RunShellCommand( > ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), > ShellInfoObject.HiiHandle, FirstParameter); > SetLastError(SHELL_NOT_FOUND); > } > - > + > +Done: > + ShellSetOriginalCmdLine(OldCmdLine); > + SHELL_FREE_NON_NULL(OldCmdLine); > SHELL_FREE_NON_NULL(CleanOriginal); > SHELL_FREE_NON_NULL(FirstParameter); > > @@ -3109,37 +3118,3 @@ RunScriptFile ( > return (Status); > } > > -/** > - Return the pointer to the first occurrence of any character from a list of > characters. > - > - @param[in] String the string to parse > - @param[in] CharacterList the list of character to look for > - @param[in] EscapeCharacter An escape character to skip > - > - @return the location of the first character in the string > - @retval CHAR_NULL no instance of any character in CharacterList was > found in String > -**/ > -CONST CHAR16* > -EFIAPI > -FindFirstCharacter( > - IN CONST CHAR16 *String, > - IN CONST CHAR16 *CharacterList, > - IN CONST CHAR16 EscapeCharacter > - ) > -{ > - UINT32 WalkChar; > - UINT32 WalkStr; > - > - for (WalkStr = 0; WalkStr < StrLen(String); WalkStr++) { > - if (String[WalkStr] == EscapeCharacter) { > - WalkStr++; > - continue; > - } > - for (WalkChar = 0; WalkChar < StrLen(CharacterList); WalkChar++) { > - if (String[WalkStr] == CharacterList[WalkChar]) { > - return (&String[WalkStr]); > - } > - } > - } > - return (String + StrLen(String)); > -} > diff --git a/ShellPkg/Application/Shell/Shell.h > b/ShellPkg/Application/Shell/Shell.h > index 29b36b0..a34c91a 100644 > --- a/ShellPkg/Application/Shell/Shell.h > +++ b/ShellPkg/Application/Shell/Shell.h > @@ -371,24 +371,6 @@ RunScriptFile ( > ); > > /** > - Return the pointer to the first occurrence of any character from a list of > characters. > - > - @param[in] String the string to parse > - @param[in] CharacterList the list of character to look for > - @param[in] EscapeCharacter An escape character to skip > - > - @return the location of the first character in the string > - @retval CHAR_NULL no instance of any character in CharacterList was > found in String > -**/ > -CONST CHAR16* > -EFIAPI > -FindFirstCharacter( > - IN CONST CHAR16 *String, > - IN CONST CHAR16 *CharacterList, > - IN CONST CHAR16 EscapeCharacter > - ); > - > -/** > Cleans off leading and trailing spaces and tabs. > > @param[in] String pointer to the string to trim them off. > diff --git a/ShellPkg/Application/Shell/ShellParametersProtocol.c > b/ShellPkg/Application/Shell/ShellParametersProtocol.c > index b3767bb..798e1d1 100644 > --- a/ShellPkg/Application/Shell/ShellParametersProtocol.c > +++ b/ShellPkg/Application/Shell/ShellParametersProtocol.c > @@ -20,162 +20,6 @@ > BOOLEAN AsciiRedirection = FALSE; > > /** > - Return the next parameter's end from a command line string. > - > - @param[in] String the string to parse > -**/ > -CONST CHAR16* > -EFIAPI > -FindEndOfParameter( > - IN CONST CHAR16 *String > - ) > -{ > - CONST CHAR16 *First; > - CONST CHAR16 *CloseQuote; > - > - First = FindFirstCharacter(String, L" \"", L'^'); > - > - // > - // nothing, all one parameter remaining > - // > - if (*First == CHAR_NULL) { > - return (First); > - } > - > - // > - // If space before a quote (or neither found, i.e. both CHAR_NULL), > - // then that's the end. > - // > - if (*First == L' ') { > - return (First); > - } > - > - CloseQuote = FindFirstCharacter (First+1, L"\"", L'^'); > - > - // > - // We did not find a terminator... > - // > - if (*CloseQuote == CHAR_NULL) { > - return (NULL); > - } > - > - return (FindEndOfParameter (CloseQuote+1)); > -} > - > -/** > - Return the next parameter from a command line string. > - > - This function moves the next parameter from Walker into TempParameter > and moves > - Walker up past that parameter for recursive calling. When the final > parameter > - is moved *Walker will be set to NULL; > - > - Temp Parameter must be large enough to hold the parameter before > calling this > - function. > - > - This will also remove all remaining ^ characters after processing. > - > - @param[in, out] Walker pointer to string of command line. > Adjusted > to > - reminaing command line on return > - @param[in, out] TempParameter pointer to string of command line item > extracted. > - @param[in] Length buffer size of TempParameter. > - @param[in] StripQuotation if TRUE then strip the quotation marks > surrounding > - the parameters. > - > - @return EFI_INALID_PARAMETER A required parameter was NULL or > pointed to a NULL or empty string. > - @return EFI_NOT_FOUND A closing " could not be found on the > specified string > -**/ > -EFI_STATUS > -EFIAPI > -GetNextParameter( > - IN OUT CHAR16 **Walker, > - IN OUT CHAR16 **TempParameter, > - IN CONST UINTN Length, > - IN BOOLEAN StripQuotation > - ) > -{ > - CONST CHAR16 *NextDelim; > - > - if (Walker == NULL > - ||*Walker == NULL > - ||TempParameter == NULL > - ||*TempParameter == NULL > - ){ > - return (EFI_INVALID_PARAMETER); > - } > - > - > - // > - // make sure we dont have any leading spaces > - // > - while ((*Walker)[0] == L' ') { > - (*Walker)++; > - } > - > - // > - // make sure we still have some params now... > - // > - if (StrLen(*Walker) == 0) { > -DEBUG_CODE_BEGIN(); > - *Walker = NULL; > -DEBUG_CODE_END(); > - return (EFI_INVALID_PARAMETER); > - } > - > - NextDelim = FindEndOfParameter(*Walker); > - > - if (NextDelim == NULL){ > -DEBUG_CODE_BEGIN(); > - *Walker = NULL; > -DEBUG_CODE_END(); > - return (EFI_NOT_FOUND); > - } > - > - StrnCpyS(*TempParameter, Length / sizeof(CHAR16), (*Walker), > NextDelim - *Walker); > - > - // > - // Add a CHAR_NULL if we didnt get one via the copy > - // > - if (*NextDelim != CHAR_NULL) { > - (*TempParameter)[NextDelim - *Walker] = CHAR_NULL; > - } > - > - // > - // Update Walker for the next iteration through the function > - // > - *Walker = (CHAR16*)NextDelim; > - > - // > - // Remove any non-escaped quotes in the string > - // Remove any remaining escape characters in the string > - // > - for (NextDelim = FindFirstCharacter(*TempParameter, L"\"^", > CHAR_NULL) > - ; *NextDelim != CHAR_NULL > - ; NextDelim = FindFirstCharacter(NextDelim, L"\"^", CHAR_NULL) > - ) { > - if (*NextDelim == L'^') { > - > - // > - // eliminate the escape ^ > - // > - CopyMem ((CHAR16*)NextDelim, NextDelim + 1, StrSize (NextDelim + > 1)); > - NextDelim++; > - } else if (*NextDelim == L'\"') { > - > - // > - // eliminate the unescaped quote > - // > - if (StripQuotation) { > - CopyMem ((CHAR16*)NextDelim, NextDelim + 1, StrSize (NextDelim + > 1)); > - } else{ > - NextDelim++; > - } > - } > - } > - > - return EFI_SUCCESS; > -} > - > -/** > Function to populate Argc and Argv. > > This function parses the CommandLine and divides it into standard C style > Argc/Argv > diff --git a/ShellPkg/Application/Shell/ShellParametersProtocol.h > b/ShellPkg/Application/Shell/ShellParametersProtocol.h > index 926f362..1205d92 100644 > --- a/ShellPkg/Application/Shell/ShellParametersProtocol.h > +++ b/ShellPkg/Application/Shell/ShellParametersProtocol.h > @@ -190,34 +190,5 @@ ParseCommandLineToArgs( > IN OUT UINTN *Argc > ); > > -/** > - return the next parameter from a command line string; > - > - This function moves the next parameter from Walker into TempParameter > and moves > - Walker up past that parameter for recursive calling. When the final > parameter > - is moved *Walker will be set to NULL; > - > - Temp Parameter must be large enough to hold the parameter before > calling this > - function. > - > - @param[in, out] Walker pointer to string of command line. > Adjusted > to > - reminaing command line on return > - @param[in, out] TempParameter pointer to string of command line item > extracted. > - @param[in] Length Length of (*TempParameter) in bytes > - @param[in] StripQuotation if TRUE then strip the quotation marks > surrounding > - the parameters. > - > - @return EFI_INALID_PARAMETER A required parameter was NULL or > pointed to a NULL or empty string. > - @return EFI_NOT_FOUND A closing " could not be found on the > specified string > -**/ > -EFI_STATUS > -EFIAPI > -GetNextParameter( > - IN OUT CHAR16 **Walker, > - IN OUT CHAR16 **TempParameter, > - IN CONST UINTN Length, > - IN BOOLEAN StripQuotation > - ); > - > #endif //_SHELL_PARAMETERS_PROTOCOL_PROVIDER_HEADER_ > > diff --git a/ShellPkg/Include/Library/ShellCommandLib.h > b/ShellPkg/Include/Library/ShellCommandLib.h > index e3bb6e0..7bec252 100644 > --- a/ShellPkg/Include/Library/ShellCommandLib.h > +++ b/ShellPkg/Include/Library/ShellCommandLib.h > @@ -5,8 +5,8 @@ > This library will not funciton if it is used for UEFI Shell 2.0 > Applications. > > Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR> > - (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR> > - (C) Copyright 2013-2014 Hewlett-Packard Development Company, L.P.<BR> > + (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR> > + (C) Copyright 2013-2014 Hewlett-Packard Development Company, > L.P.<BR> > This program and the accompanying materials > are licensed and made available under the terms and conditions of the BSD > License > which accompanies this distribution. The full text of the license may be > found at > @@ -670,6 +670,29 @@ ShellFileHandleEof( > IN SHELL_FILE_HANDLE Handle > ); > > +/** > + Function to get the original CmdLine string for current command. > + > + @return A pointer to the buffer of the original command string. > + It's the caller's responsibility to free the buffer. > +**/ > +CHAR16* > +EFIAPI > +ShellGetOriginalCmdLine( > + VOID > + ); > + > +/** > + Function to store the orgignal command string into mOriginalCmdLine. > + > + @param[in] CmdLine the command line string to store. > +**/ > +VOID > +EFIAPI > +ShellSetOriginalCmdLine( > + IN CONST CHAR16 *CmdLine > + ); > + > typedef struct { > LIST_ENTRY Link; > void *Buffer; > @@ -702,21 +725,80 @@ DumpHex ( > IN VOID *UserData > ); > > -/** > - Dump HEX data into buffer. > - > - @param[in] Buffer HEX data to be dumped in Buffer. > - @param[in] Indent How many spaces to indent the output. > - @param[in] Offset The offset of the printing. > - @param[in] DataSize The size in bytes of UserData. > - @param[in] UserData The data to print out. > -**/ > -CHAR16* > -CatSDumpHex ( > - IN CHAR16 *Buffer, > - IN UINTN Indent, > - IN UINTN Offset, > - IN UINTN DataSize, > - IN VOID *UserData > - ); > +/** > + Dump HEX data into buffer. > + > + @param[in] Buffer HEX data to be dumped in Buffer. > + @param[in] Indent How many spaces to indent the output. > + @param[in] Offset The offset of the printing. > + @param[in] DataSize The size in bytes of UserData. > + @param[in] UserData The data to print out. > +**/ > +CHAR16* > +CatSDumpHex ( > + IN CHAR16 *Buffer, > + IN UINTN Indent, > + IN UINTN Offset, > + IN UINTN DataSize, > + IN VOID *UserData > + ); > + > +/** > + Return the pointer to the first occurrence of any character from a list of > characters. > + > + @param[in] String the string to parse > + @param[in] CharacterList the list of character to look for > + @param[in] EscapeCharacter An escape character to skip > + > + @return the location of the first character in the string > + @retval CHAR_NULL no instance of any character in CharacterList was > found in String > +**/ > +CONST CHAR16* > +EFIAPI > +FindFirstCharacter( > + IN CONST CHAR16 *String, > + IN CONST CHAR16 *CharacterList, > + IN CONST CHAR16 EscapeCharacter > + ); > + > +/** > + Return the next parameter's end from a command line string. > + > + @param[in] String the string to parse > +**/ > +CONST CHAR16* > +EFIAPI > +FindEndOfParameter( > + IN CONST CHAR16 *String > + ); > + > +/** > + return the next parameter from a command line string; > + > + This function moves the next parameter from Walker into TempParameter > and moves > + Walker up past that parameter for recursive calling. When the final > parameter > + is moved *Walker will be set to NULL; > + > + Temp Parameter must be large enough to hold the parameter before > calling this > + function. > + > + @param[in, out] Walker pointer to string of command line. > Adjusted > to > + reminaing command line on return > + @param[in, out] TempParameter pointer to string of command line item > extracted. > + @param[in] Length Length of (*TempParameter) in bytes > + @param[in] StripQuotation if TRUE then strip the quotation marks > surrounding > + the parameters. > + > + @return EFI_INALID_PARAMETER A required parameter was NULL or > pointed to a NULL or empty string. > + @return EFI_NOT_FOUND A closing " could not be found on the > specified string > +**/ > +EFI_STATUS > +EFIAPI > +GetNextParameter( > + IN OUT CHAR16 **Walker, > + IN OUT CHAR16 **TempParameter, > + IN CONST UINTN Length, > + IN BOOLEAN StripQuotation > + ); > + > #endif //_SHELL_COMMAND_LIB_ > diff --git a/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c > b/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c > index 48e4d4a..e3c436a 100644 > --- a/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c > +++ b/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c > @@ -2,9 +2,9 @@ > Provides interface to shell internal functions for shell commands. > > Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR> > - (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR> > - (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR> > - > + (C) Copyright 2013-2015 Hewlett-Packard Development Company, > L.P.<BR> > + (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR> > + > This program and the accompanying materials > are licensed and made available under the terms and conditions of the BSD > License > which accompanies this distribution. The full text of the license may be > found at > @@ -30,6 +30,7 @@ STATIC UINTN mProfileListSize; > STATIC UINTN mFsMaxCount = 0; > STATIC UINTN mBlkMaxCount = 0; > STATIC BUFFER_LIST mFileHandleList; > +STATIC CHAR16 *mOriginalCmdLine = NULL; > > STATIC CONST CHAR8 Hex[] = { > '0', > @@ -83,6 +84,199 @@ CommandInit( > } > > /** > + Return the pointer to the first occurrence of any character from a list of > characters. > + > + @param[in] String the string to parse > + @param[in] CharacterList the list of character to look for > + @param[in] EscapeCharacter An escape character to skip > + > + @return the location of the first character in the string > + @retval CHAR_NULL no instance of any character in CharacterList was > found in String > +**/ > +CONST CHAR16* > +EFIAPI > +FindFirstCharacter( > + IN CONST CHAR16 *String, > + IN CONST CHAR16 *CharacterList, > + IN CONST CHAR16 EscapeCharacter > + ) > +{ > + UINT32 WalkChar; > + UINT32 WalkStr; > + > + for (WalkStr = 0; WalkStr < StrLen(String); WalkStr++) { > + if (String[WalkStr] == EscapeCharacter) { > + WalkStr++; > + continue; > + } > + for (WalkChar = 0; WalkChar < StrLen(CharacterList); WalkChar++) { > + if (String[WalkStr] == CharacterList[WalkChar]) { > + return (&String[WalkStr]); > + } > + } > + } > + return (String + StrLen(String)); > +} > + > + > +/** > + Return the next parameter's end from a command line string. > + > + @param[in] String the string to parse > +**/ > +CONST CHAR16* > +EFIAPI > +FindEndOfParameter( > + IN CONST CHAR16 *String > + ) > +{ > + CONST CHAR16 *First; > + CONST CHAR16 *CloseQuote; > + > + First = FindFirstCharacter(String, L" \"", L'^'); > + > + // > + // nothing, all one parameter remaining > + // > + if (*First == CHAR_NULL) { > + return (First); > + } > + > + // > + // If space before a quote (or neither found, i.e. both CHAR_NULL), > + // then that's the end. > + // > + if (*First == L' ') { > + return (First); > + } > + > + CloseQuote = FindFirstCharacter (First+1, L"\"", L'^'); > + > + // > + // We did not find a terminator... > + // > + if (*CloseQuote == CHAR_NULL) { > + return (NULL); > + } > + > + return (FindEndOfParameter (CloseQuote+1)); > +} > + > +/** > + Return the next parameter from a command line string. > + > + This function moves the next parameter from Walker into TempParameter > and moves > + Walker up past that parameter for recursive calling. When the final > parameter > + is moved *Walker will be set to NULL; > + > + Temp Parameter must be large enough to hold the parameter before > calling this > + function. > + > + This will also remove all remaining ^ characters after processing. > + > + @param[in, out] Walker pointer to string of command line. > Adjusted > to > + reminaing command line on return > + @param[in, out] TempParameter pointer to string of command line item > extracted. > + @param[in] Length buffer size of TempParameter. > + @param[in] StripQuotation if TRUE then strip the quotation marks > surrounding > + the parameters. > + > + @return EFI_INALID_PARAMETER A required parameter was NULL or > pointed to a NULL or empty string. > + @return EFI_NOT_FOUND A closing " could not be found on the > specified string > +**/ > +EFI_STATUS > +EFIAPI > +GetNextParameter( > + IN OUT CHAR16 **Walker, > + IN OUT CHAR16 **TempParameter, > + IN CONST UINTN Length, > + IN BOOLEAN StripQuotation > + ) > +{ > + CONST CHAR16 *NextDelim; > + > + if (Walker == NULL > + ||*Walker == NULL > + ||TempParameter == NULL > + ||*TempParameter == NULL > + ){ > + return (EFI_INVALID_PARAMETER); > + } > + > + > + // > + // make sure we dont have any leading spaces > + // > + while ((*Walker)[0] == L' ') { > + (*Walker)++; > + } > + > + // > + // make sure we still have some params now... > + // > + if (StrLen(*Walker) == 0) { > +DEBUG_CODE_BEGIN(); > + *Walker = NULL; > +DEBUG_CODE_END(); > + return (EFI_INVALID_PARAMETER); > + } > + > + NextDelim = FindEndOfParameter(*Walker); > + > + if (NextDelim == NULL){ > +DEBUG_CODE_BEGIN(); > + *Walker = NULL; > +DEBUG_CODE_END(); > + return (EFI_NOT_FOUND); > + } > + > + StrnCpyS(*TempParameter, Length / sizeof(CHAR16), (*Walker), > NextDelim - *Walker); > + > + // > + // Add a CHAR_NULL if we didnt get one via the copy > + // > + if (*NextDelim != CHAR_NULL) { > + (*TempParameter)[NextDelim - *Walker] = CHAR_NULL; > + } > + > + // > + // Update Walker for the next iteration through the function > + // > + *Walker = (CHAR16*)NextDelim; > + > + // > + // Remove any non-escaped quotes in the string > + // Remove any remaining escape characters in the string > + // > + for (NextDelim = FindFirstCharacter(*TempParameter, L"\"^", > CHAR_NULL) > + ; *NextDelim != CHAR_NULL > + ; NextDelim = FindFirstCharacter(NextDelim, L"\"^", CHAR_NULL) > + ) { > + if (*NextDelim == L'^') { > + > + // > + // eliminate the escape ^ > + // > + CopyMem ((CHAR16*)NextDelim, NextDelim + 1, StrSize (NextDelim + > 1)); > + NextDelim++; > + } else if (*NextDelim == L'\"') { > + > + // > + // eliminate the unescaped quote > + // > + if (StripQuotation) { > + CopyMem ((CHAR16*)NextDelim, NextDelim + 1, StrSize (NextDelim + > 1)); > + } else{ > + NextDelim++; > + } > + } > + } > + > + return EFI_SUCCESS; > +} > + > + > +/** > Constructor for the Shell Command library. > > Initialize the library and determine if the underlying is a UEFI Shell 2.0 > or an > EFI shell. > @@ -1664,6 +1858,51 @@ ShellFileHandleEof( > } > > /** > + Function to get the original CmdLine string for current command. > + > + @return A pointer to the buffer of the original command string. > + It's the caller's responsibility to free the buffer. > +**/ > +CHAR16* > +EFIAPI > +ShellGetOriginalCmdLine( > + VOID > + ) > +{ > + CHAR16 *RetCmdLine; > + > + if (mOriginalCmdLine == NULL) { > + return NULL; > + } else { > + RetCmdLine = AllocateCopyPool(StrSize(mOriginalCmdLine), > mOriginalCmdLine); > + ASSERT (RetCmdLine != NULL); > + > + return RetCmdLine; > + } > +} > + > +/** > + Function to store the orgignal command string into mOriginalCmdLine. > + > + @param[in] CmdLine the command line string to store. > +**/ > +VOID > +EFIAPI > +ShellSetOriginalCmdLine( > + IN CONST CHAR16 *CmdLine > + ) > +{ > + SHELL_FREE_NON_NULL(mOriginalCmdLine); > + > + if (CmdLine != NULL) { > + mOriginalCmdLine = AllocateCopyPool (StrSize(CmdLine), CmdLine); > + ASSERT(mOriginalCmdLine); > + } > + > +} > + > + > +/** > Frees any BUFFER_LIST defined type. > > @param[in] List The BUFFER_LIST object to free. > @@ -1744,60 +1983,61 @@ DumpHex ( > DataSize -= Size; > } > } > - > -/** > - Dump HEX data into buffer. > - > - @param[in] Buffer HEX data to be dumped in Buffer. > - @param[in] Indent How many spaces to indent the output. > - @param[in] Offset The offset of the printing. > - @param[in] DataSize The size in bytes of UserData. > - @param[in] UserData The data to print out. > -**/ > -CHAR16* > -CatSDumpHex ( > - IN CHAR16 *Buffer, > - IN UINTN Indent, > - IN UINTN Offset, > - IN UINTN DataSize, > - IN VOID *UserData > - ) > -{ > - UINT8 *Data; > - UINT8 TempByte; > - UINTN Size; > - UINTN Index; > - CHAR8 Val[50]; > - CHAR8 Str[20]; > - CHAR16 *RetVal; > - CHAR16 *TempRetVal; > - > - Data = UserData; > - RetVal = Buffer; > - while (DataSize != 0) { > - Size = 16; > - if (Size > DataSize) { > - Size = DataSize; > - } > - > - for (Index = 0; Index < Size; Index += 1) { > - TempByte = Data[Index]; > - Val[Index * 3 + 0] = Hex[TempByte >> 4]; > - Val[Index * 3 + 1] = Hex[TempByte & 0xF]; > - Val[Index * 3 + 2] = (CHAR8) ((Index == 7) ? '-' : ' '); > - Str[Index] = (CHAR8) ((TempByte < ' ' || TempByte > 'z') ? > '.' : > TempByte); > - } > - > - Val[Index * 3] = 0; > - Str[Index] = 0; > - TempRetVal = CatSPrint (RetVal, L"%*a%08X: %-48a *%a*\r\n", Indent, > "", Offset, Val, Str); > - SHELL_FREE_NON_NULL (RetVal); > - RetVal = TempRetVal; > - > - Data += Size; > - Offset += Size; > - DataSize -= Size; > - } > - > - return RetVal; > -} > + > +/** > + Dump HEX data into buffer. > + > + @param[in] Buffer HEX data to be dumped in Buffer. > + @param[in] Indent How many spaces to indent the output. > + @param[in] Offset The offset of the printing. > + @param[in] DataSize The size in bytes of UserData. > + @param[in] UserData The data to print out. > +**/ > +CHAR16* > +CatSDumpHex ( > + IN CHAR16 *Buffer, > + IN UINTN Indent, > + IN UINTN Offset, > + IN UINTN DataSize, > + IN VOID *UserData > + ) > +{ > + UINT8 *Data; > + UINT8 TempByte; > + UINTN Size; > + UINTN Index; > + CHAR8 Val[50]; > + CHAR8 Str[20]; > + CHAR16 *RetVal; > + CHAR16 *TempRetVal; > + > + Data = UserData; > + RetVal = Buffer; > + while (DataSize != 0) { > + Size = 16; > + if (Size > DataSize) { > + Size = DataSize; > + } > + > + for (Index = 0; Index < Size; Index += 1) { > + TempByte = Data[Index]; > + Val[Index * 3 + 0] = Hex[TempByte >> 4]; > + Val[Index * 3 + 1] = Hex[TempByte & 0xF]; > + Val[Index * 3 + 2] = (CHAR8) ((Index == 7) ? '-' : ' '); > + Str[Index] = (CHAR8) ((TempByte < ' ' || TempByte > 'z') ? > '.' : > TempByte); > + } > + > + Val[Index * 3] = 0; > + Str[Index] = 0; > + TempRetVal = CatSPrint (RetVal, L"%*a%08X: %-48a *%a*\r\n", Indent, > "", Offset, Val, Str); > + SHELL_FREE_NON_NULL (RetVal); > + RetVal = TempRetVal; > + > + Data += Size; > + Offset += Size; > + DataSize -= Size; > + } > + > + return RetVal; > +} > + > diff --git a/ShellPkg/Library/UefiShellLevel3CommandsLib/Echo.c > b/ShellPkg/Library/UefiShellLevel3CommandsLib/Echo.c > index a638de8..289697a 100644 > --- a/ShellPkg/Library/UefiShellLevel3CommandsLib/Echo.c > +++ b/ShellPkg/Library/UefiShellLevel3CommandsLib/Echo.c > @@ -2,7 +2,7 @@ > Main file for Echo shell level 3 function. > > (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR> > - Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved. <BR> > + Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved. <BR> > This program and the accompanying materials > are licensed and made available under the terms and conditions of the BSD > License > which accompanies this distribution. The full text of the license may be > found at > @@ -17,12 +17,6 @@ > > #include <Library/ShellLib.h> > > -STATIC CONST SHELL_PARAM_ITEM ParamList[] = { > - {L"-on", TypeFlag}, > - {L"-off", TypeFlag}, > - {NULL, TypeMax} > - }; > - > /** > Function for 'echo' command. > > @@ -36,86 +30,85 @@ ShellCommandRunEcho ( > IN EFI_SYSTEM_TABLE *SystemTable > ) > { > - EFI_STATUS Status; > - LIST_ENTRY *Package; > - SHELL_STATUS ShellStatus; > - UINTN ParamCount; > - CHAR16 *ProblemParam; > + CHAR16 *OriginalCmdLine; > + SHELL_STATUS Status; > UINTN Size; > CHAR16 *PrintString; > + CHAR16 *Walker; > + CHAR16 *TempParameter; > + BOOLEAN OnFlag; > + BOOLEAN OffFlag; > + UINTN Count; > + > + OriginalCmdLine = ShellGetOriginalCmdLine(); > + if (OriginalCmdLine == NULL) { > + return SHELL_OUT_OF_RESOURCES; > + } > > Size = 0; > - ProblemParam = NULL; > PrintString = NULL; > - ShellStatus = SHELL_SUCCESS; > - > - // > - // initialize the shell lib (we must be in non-auto-init...) > - // > - Status = ShellInitialize(); > - ASSERT_EFI_ERROR(Status); > - > - // > - // parse the command line > - // > - Status = ShellCommandLineParseEx (ParamList, &Package, > &ProblemParam, TRUE, TRUE); > - if (EFI_ERROR(Status)) { > - if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { > - ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), > gShellLevel3HiiHandle, L"echo", ProblemParam); > - FreePool(ProblemParam); > - ShellStatus = SHELL_INVALID_PARAMETER; > - } else { > - ASSERT(FALSE); > - } > - } else { > - // > - // check for "-?" > - // > - if (ShellCommandLineGetFlag(Package, L"-?")) { > - ASSERT(FALSE); > + TempParameter = NULL; > + Status = EFI_SUCCESS; > + OnFlag = FALSE; > + OffFlag = FALSE; > + > + Size = StrSize(OriginalCmdLine); > + TempParameter = AllocateZeroPool(Size); > + ASSERT (TempParameter != NULL); > + > + for ( Count = 0 > + , Walker = (CHAR16*)OriginalCmdLine > + ; Walker != NULL && *Walker != CHAR_NULL > + ; Count++ > + ) { > + if (EFI_ERROR(GetNextParameter(&Walker, &TempParameter, Size, > FALSE))) { > + break; > } > - if (ShellCommandLineGetFlag(Package, L"-on")) { > - // > - // Turn it on > - // > - ShellCommandSetEchoState(TRUE); > - } else if (ShellCommandLineGetFlag(Package, L"-off")) { > - // > - // turn it off > - // > - ShellCommandSetEchoState(FALSE); > - } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) { > - // > - // output its current state > - // > - if (ShellCommandGetEchoState()) { > - ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_ECHO_ON), > gShellLevel3HiiHandle); > - } else { > - ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_ECHO_OFF), > gShellLevel3HiiHandle); > + > + if (Count == 1) { > + if (gUnicodeCollation->StriColl(gUnicodeCollation, TempParameter, L"- > on") == 0 ) { > + OnFlag = TRUE; > } > - } else { > - // > - // print the line > - // > - for ( ParamCount = 1 > - ; ShellCommandLineGetRawValue(Package, ParamCount) != NULL > - ; ParamCount++ > - ) { > - StrnCatGrow(&PrintString, &Size, > ShellCommandLineGetRawValue(Package, ParamCount), 0); > - if (ShellCommandLineGetRawValue(Package, ParamCount+1) != NULL) { > - StrnCatGrow(&PrintString, &Size, L" ", 0); > - } > + if (gUnicodeCollation->StriColl(gUnicodeCollation, TempParameter, L"- > off") == 0 ) { > + OffFlag = TRUE; > } > - ShellPrintEx(-1, -1, L"%s\r\n", PrintString); > - SHELL_FREE_NON_NULL(PrintString); > } > + } > + > + if ((OnFlag || OffFlag) && Count != 2 ) { > + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN > (STR_ECHO_INVALID_PARAM), gShellLevel3HiiHandle, L"echo", L"-on/-off"); > + Status = SHELL_INVALID_PARAMETER; > + goto Done; > + } > > - // > - // free the command line package > - // > - ShellCommandLineFreeVarList (Package); > + if (OnFlag) { > + ShellCommandSetEchoState(TRUE); > + Status = SHELL_SUCCESS; > + goto Done; > + } else if (OffFlag) { > + ShellCommandSetEchoState(FALSE); > + Status = SHELL_SUCCESS; > + goto Done; > } > > - return (ShellStatus); > + Walker = OriginalCmdLine + StrLen(L"echo"); > + if (StrLen (Walker) <= 1) { > + Status = SHELL_SUCCESS; > + goto Done; > + } else { > + Walker++; > + PrintString = AllocateCopyPool(StrSize(Walker), Walker); > + ASSERT (PrintString != NULL); > + ShellPrintEx(-1, -1, L"%s\r\n", PrintString); > + } > + > + Status = SHELL_SUCCESS; > + > +Done: > + SHELL_FREE_NON_NULL(TempParameter); > + SHELL_FREE_NON_NULL(PrintString); > + SHELL_FREE_NON_NULL(OriginalCmdLine); > + return Status; > + > } > > diff --git > a/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3Commands > Lib.uni > b/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3Commands > Lib.uni > index fc9c5d4..f6978d2 100644 > --- > a/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3Commands > Lib.uni > +++ > b/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3Commands > Lib.uni > @@ -55,6 +55,7 @@ > > #string STR_ECHO_ON #language en-US "Echo is on.\r\n" > #string STR_ECHO_OFF #language en-US "Echo is off.\r\n" > +#string STR_ECHO_INVALID_PARAM #language en-US "%H%s%N: Invalid > - too many parameters after '%s'\r\n" > > #string STR_PAUSE_PROMPT #language en-US "Enter 'q' to quit, any > other key to continue:\r\n" > > -- > 2.7.1.windows.2 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel