From: "Vladimir Olovyannikov" <vladimir.olovyannikov@broadcom.com>
To: "Ni, Ray" <ray.ni@intel.com>,
devel@edk2.groups.io, "Gao, Zhichao" <zhichao.gao@intel.com>
Subject: Re: [edk2-devel] [PATCH 1/1] ShellPkg/Application: Support nested variables substitution from cmd line
Date: Fri, 10 Jan 2020 08:32:37 -0800 [thread overview]
Message-ID: <2d6b2d376dfef281c2ec66b35d0735f8@mail.gmail.com> (raw)
In-Reply-To: <734D49CCEBEEF84792F5B80ED585239D5C3E6CF4@SHSMSX104.ccr.corp.intel.com>
Hi Ray,
As an example, let's say that you have multiple variants of serverips -
each interface has its own, and each interface has a property as say
interface no (eth_no).
It is logical to address a serverip for an interface as
%serverip%eth_no%%, and in the end get the contents of variable serverip0
(say for eth_no containing value 0).
In fact, Linux bash allows doing that easily.
We are doing most of our upgrade/configuration stuff via Shell scripts
which is very flexible, easy and efficient.
To support boot redundancy, we support multiple slots for kernel/dtbs,
etc, which are addressed as
%update_type_%upd_type%% where upd_type can be dtb, kernel, etc.
The spec says " Environment variables can be used on the command-line by
using %variable-name%
where variable-name is the environment variable's name. Variable
substitution is not recursive."
I treat it as an extension to %var% case; %var case is not touched. What
do you think?
Regarding unit tests.
I verified variables substitutions using %var% and %var%var1%% and
%%var1%var% to make sure there would be no regression.
Our scripts use variables extensively, and no issues were encountered.
Please let me know if you need the scripts we are using, and I will send
them to you.
Which unit tests are available?
Thank you,
Vladimir
-----Original Message-----
From: Ni, Ray <ray.ni@intel.com>
Sent: Thursday, January 9, 2020 10:03 PM
To: devel@edk2.groups.io; vladimir.olovyannikov@broadcom.com; Gao, Zhichao
<zhichao.gao@intel.com>
Subject: RE: [edk2-devel] [PATCH 1/1] ShellPkg/Application: Support nested
variables substitution from cmd line
Vladimir,
Is this enhancement an extension to Shell spec or violation of Shell spec?
If it's an extension, I am happy to have such feature implemented.
Otherwise, we may need to discuss in uefi.org.
Can you list the unit tests you have done?
Thanks,
Ray
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of
> Vladimir Olovyannikov via Groups.Io
> Sent: Friday, January 10, 2020 6:07 AM
> To: devel@edk2.groups.io; Ni, Ray <ray.ni@intel.com>; Gao, Zhichao
> <zhichao.gao@intel.com>
> Cc: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>
> Subject: [edk2-devel] [PATCH 1/1] ShellPkg/Application: Support nested
> variables substitution from cmd line
>
> The current implementation of ShellSubstituteVariables() does not
> allow substitution of variables names containing another variable
> name(s) between %...%
>
> Example: %text%var_name%% where var_name variable contains 0.
> Here the variable value which should be returned on substitution would
> be contents of text0 variable.
> The current implementation would return nothing as %text0% would be
> eliminated by StripUnreplacedEnvironmentVariables().
>
> Modify the code so that StripUnreplacedEnvironmentVariables checks if
> variable between %...% really exists. If it does not, delete %...%.
> If it exists, preserve it and tell the caller that another run of
> ShellConvertVariables() is needed. This way, any nested variable
> between %...% can be easily retrieved.
> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2452
>
> Signed-off-by: Vladimir Olovyannikov
> <vladimir.olovyannikov@broadcom.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> ---
> ShellPkg/Application/Shell/Shell.c | 71
> ++++++++++++++++++++++++------
> 1 file changed, 57 insertions(+), 14 deletions(-)
>
> diff --git a/ShellPkg/Application/Shell/Shell.c
> b/ShellPkg/Application/Shell/Shell.c
> index d16adae0ea30..3756a71794d1 100644
> --- a/ShellPkg/Application/Shell/Shell.c
> +++ b/ShellPkg/Application/Shell/Shell.c
> @@ -1510,12 +1510,16 @@ ShellConvertAlias(
>
> /**
> This function will eliminate unreplaced (and therefore non-found)
environment variables.
> -
> + If a variable exists between %...%, it will be preserved, and
> + VarExists would be TRUE.
> @param[in,out] CmdLine The command line to update.
> + @param[out] VarExists A pointer to the BOOLEAN which is set if
> + a Shell variable between %...% exists.
> **/
> EFI_STATUS
> StripUnreplacedEnvironmentVariables(
> - IN OUT CHAR16 *CmdLine
> + IN OUT CHAR16 *CmdLine,
> + OUT BOOLEAN *VarExists
> )
> {
> CHAR16 *FirstPercent;
> @@ -1558,12 +1562,38 @@ StripUnreplacedEnvironmentVariables(
> if (FirstQuote == NULL || SecondPercent < FirstQuote) {
> if (IsValidEnvironmentVariableName(FirstPercent, SecondPercent))
{
> //
> - // We need to remove from FirstPercent to SecondPercent
> - //
> - CopyMem(FirstPercent, SecondPercent + 1, StrSize(SecondPercent
+ 1));
> - //
> - // don't need to update the locator. both % characters are
gone.
> + // If this Shell variable exists, consider that another run is
needed.
> + // For example, consider a variable %var%var2%% when var2 is 0.
> + // After the first run, it becomes %var0%, and after the second
run
> + // it contains the value of var0 variable.
> + // Eliminate variable if it does not exist.
> //
> + CHAR16 *VarName;
> +
> + // Consider NULL terminator as well
> + VarName = (CHAR16 *)AllocateZeroPool((SecondPercent -
FirstPercent) *
> + sizeof(CHAR16));
> + if (VarName) {
> + CopyMem(VarName, FirstPercent + 1,
> + (SecondPercent - FirstPercent - 1) * sizeof(CHAR16));
> + }
> +
> + if (!VarName || !ShellGetEnvironmentVariable(VarName)) {
> + //
> + // We need to remove from FirstPercent to SecondPercent.
> + //
> + CopyMem(FirstPercent, SecondPercent + 1,
StrSize(SecondPercent + 1));
> + //
> + // don't need to update the locator. both % characters are
gone.
> + //
> + } else {
> + *VarExists = TRUE;
> + //
> + // In this case, locator needs to be updated as % characters
present.
> + //
> + CurrentLocator = SecondPercent + 1;
> + }
> + SHELL_FREE_NON_NULL(VarName);
> } else {
> CurrentLocator = SecondPercent + 1;
> }
> @@ -1581,13 +1611,18 @@ StripUnreplacedEnvironmentVariables(
> If the return value is not NULL the memory must be caller freed.
>
> @param[in] OriginalCommandLine The original command line
> + @param[out] NeedExtraRun Indication that the caller needs to
repeat
> + this call to convert variables as
there are
> + existing variable(s) between %..%
> + present after the call.
>
> @retval NULL An error occurred.
> @return The new command line with no
environment variables present.
> **/
> CHAR16*
> ShellConvertVariables (
> - IN CONST CHAR16 *OriginalCommandLine
> + IN CONST CHAR16 *OriginalCommandLine,
> + OUT BOOLEAN *NeedExtraRun
> )
> {
> CONST CHAR16 *MasterEnvList;
> @@ -1601,11 +1636,13 @@ ShellConvertVariables (
> ALIAS_LIST *AliasListNode;
>
> ASSERT(OriginalCommandLine != NULL);
> + ASSERT(NeedExtraRun != NULL);
>
> ItemSize = 0;
> NewSize = StrSize(OriginalCommandLine);
> CurrentScriptFile = ShellCommandGetCurrentScriptFile();
> Temp = NULL;
> + *NeedExtraRun = FALSE;
>
> ///@todo update this to handle the %0 - %9 for scripting only (borrow
from line 1256 area) ? ? ?
>
> @@ -1698,7 +1735,7 @@ ShellConvertVariables (
> //
> // Remove non-existent environment variables
> //
> - StripUnreplacedEnvironmentVariables(NewCommandLine1);
> + StripUnreplacedEnvironmentVariables(NewCommandLine1, NeedExtraRun);
>
> //
> // Now cleanup any straggler intentionally ignored "%" characters
> @@ -1845,12 +1882,18 @@ ShellSubstituteVariables(
> )
> {
> CHAR16 *NewCmdLine;
> - NewCmdLine = ShellConvertVariables(*CmdLine);
> - SHELL_FREE_NON_NULL(*CmdLine);
> - if (NewCmdLine == NULL) {
> - return (EFI_OUT_OF_RESOURCES);
> + BOOLEAN NeedExtraRun;
> +
> + NeedExtraRun = TRUE;
> + while (NeedExtraRun) {
> + NewCmdLine = ShellConvertVariables(*CmdLine, &NeedExtraRun);
> + SHELL_FREE_NON_NULL(*CmdLine);
> + if (NewCmdLine == NULL) {
> + return (EFI_OUT_OF_RESOURCES);
> + }
> + *CmdLine = NewCmdLine;
> }
> - *CmdLine = NewCmdLine;
> +
> return (EFI_SUCCESS);
> }
>
> --
> 2.17.1
>
>
>
next prev parent reply other threads:[~2020-01-10 16:32 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-01-09 22:06 [PATCH 1/1] ShellPkg/Application: Support nested variables substitution from cmd line Vladimir Olovyannikov
2020-01-10 6:02 ` [edk2-devel] " Ni, Ray
2020-01-10 16:32 ` Vladimir Olovyannikov [this message]
2020-01-13 3:06 ` Gao, Zhichao
2020-01-14 17:33 ` Vladimir Olovyannikov
2020-01-13 0:49 ` Liming Gao
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2d6b2d376dfef281c2ec66b35d0735f8@mail.gmail.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox