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

Reply via email to