From: "Carsey, Jaben" <jaben.carsey@intel.com>
To: "Ni, Ruiyu" <ruiyu.ni@intel.com>,
"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Cc: "Chen, Chen A" <chen.a.chen@intel.com>,
"Carsey, Jaben" <jaben.carsey@intel.com>
Subject: Re: [PATCH 2/2] ShellPkg/cd: Fix "cd" to support "fs0:dir" (no slash after ':')
Date: Wed, 21 Dec 2016 16:23:15 +0000 [thread overview]
Message-ID: <CB6E33457884FA40993F35157061515C54B2D5A2@FMSMSX103.amr.corp.intel.com> (raw)
In-Reply-To: <20161221085501.159796-3-ruiyu.ni@intel.com>
> -----Original Message-----
> From: Ni, Ruiyu
> Sent: Wednesday, December 21, 2016 12:55 AM
> To: edk2-devel@lists.01.org
> Cc: Chen, Chen A <chen.a.chen@intel.com>; Carsey, Jaben
> <jaben.carsey@intel.com>
> Subject: [PATCH 2/2] ShellPkg/cd: Fix "cd" to support "fs0:dir" (no slash after
> ':')
> Importance: High
>
> When "fs0:dir"(drive letter without slash) is used as destination
> of "cd", "cd" tries to change to "dir" in root directory of "fs0:".
> It's incorrect. The correct behavior is to change to "dir" in
> current directory of "fs0:"
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
> Signed-off-by: Chen A Chen <chen.a.chen@intel.com>
> Cc: Jaben Carsey <jaben.carsey@intel.com>
> ---
> ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c | 415 +++++++++++++--
> --------
> 1 file changed, 240 insertions(+), 175 deletions(-)
>
> diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c
> b/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c
> index 0967bc7..0b4becf 100644
> --- a/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c
> +++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c
> @@ -17,6 +17,156 @@
> #include "UefiShellLevel2CommandsLib.h"
>
> /**
> + Function will replace drive identifier with CWD.
> +
> + If FullPath begining with ':' is invalid path, then ASSERT.
Is there any way for the user from the shell prompt to hit the ASSERT? Is there a good reason to use ASSERT and not just return an error (NULL for example)?
> + If FullPath not include dirve identifier , then do nothing.
> + If FullPath likes "fs0:\xx" or "fs0:/xx" , then do nothing.
> + If FullPath likes "fs0:xxx" or "fs0:", the drive replaced by CWD.
> +
> + @param[in, out] FullPath The pointer to the string containing the path.
> + @param[in] Cwd Current directory.
> +
> + @retval EFI_SUCCESS Success.
> + @retval EFI_OUT_OF_SOURCES A memory allocation failed.
> +**/
> +EFI_STATUS
> +ReplaceDriveWithCwd(
> + IN OUT CHAR16 **FullPath,
> + IN CONST CHAR16 *Cwd
> + )
> +{
> + CHAR16 *Splitter;
> + CHAR16 *TempBuffer;
> + UINTN TotalSize;
> +
> + Splitter = NULL;
> + TempBuffer = NULL;
> + TotalSize = 0;
> +
> + if (FullPath == NULL || *FullPath == NULL) {
> + return EFI_SUCCESS;
> + }
> +
> + Splitter = StrStr (*FullPath, L":");
> + ASSERT(Splitter != *FullPath);
> +
> + if (Splitter != NULL && *(Splitter + 1) != L'\\' && *(Splitter + 1) != L'/') {
> + TotalSize = StrSize (Cwd) + StrSize (Splitter + 1);
> + TempBuffer = AllocateZeroPool (TotalSize);
> + if (TempBuffer == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + StrCpyS (TempBuffer, TotalSize / sizeof(CHAR16), Cwd);
> + StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), L"\\");
> + StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), Splitter + 1);
> +
> + FreePool(*FullPath);
> + *FullPath = TempBuffer;
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + function to determine if FullPath is under current filesystem.
> +
> + @param[in] FullPath The target location to determine.
> + @param[in] Cwd Current directory.
> +
> + @retval TRUE The FullPath is in the current filesystem.
> + @retval FALSE The FullPaht isn't in the current filesystem.
> +**/
> +BOOLEAN
> +IsCurrentFileSystem(
> + IN CONST CHAR16 *FullPath,
> + IN CONST CHAR16 *Cwd
> + )
> +{
> + CHAR16 *Splitter1;
> + CHAR16 *Splitter2;
> +
> + Splitter1 = NULL;
> + Splitter2 = NULL;
> +
> + ASSERT(FullPath != NULL);
> +
> + Splitter1 = StrStr (FullPath, L":");
> + if (Splitter1 == NULL) {
> + return TRUE;
> + }
> +
> + Splitter2 = StrStr (Cwd, L":");
> +
> + if ((UINTN)(Splitter1 - FullPath) != (UINTN)(Splitter2 - Cwd)) {
> + return FALSE;
> + } else {
> + if (StrniCmp(FullPath, Cwd, (UINTN)(Splitter1 - FullPath)) == NULL) {
> + return TRUE;
> + } else {
> + return FALSE;
> + }
> + }
> +}
> +
> +/**
> + Extract drive string and path string from FullPath.
> +
> + The caller must be free Drive and Path.
> +
> + @param[in] FullPath A path to be extracted.
> + @param[out] Drive Buffer to save drive identifier.
> + @param[out] Path Buffer to save path.
> +
> + @retval EFI_SUCCESS Success.
> + @retval EFI_OUT_OF_RESOUCES A memory allocation failed.
> +**/
> +EFI_STATUS
> +ExtractDriveAndPath(
> + IN CONST CHAR16 *FullPath,
> + OUT CHAR16 **Drive,
> + OUT CHAR16 **Path
> + )
> +{
> + CHAR16 *Splitter;
> +
> + ASSERT(FullPath != NULL);
> +
> + Splitter = StrStr (FullPath, L":");
> +
> + if (Splitter == NULL) {
> + *Drive = NULL;
> + *Path = AllocateCopyPool (StrSize (FullPath), FullPath);
> + if (*Path == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> + } else {
> + if (*(Splitter + 1) == CHAR_NULL) {
> + *Drive = AllocateCopyPool (StrSize (FullPath), FullPath);
> + *Path = NULL;
> + if (*Drive == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> + } else {
> + *Drive = AllocateCopyPool((Splitter - FullPath + 2) * sizeof(CHAR16),
> FullPath);
> + if (*Drive == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> + (*Drive)[Splitter - FullPath + 1] = CHAR_NULL;
> +
> + *Path = AllocateCopyPool (StrSize (Splitter + 1), Splitter + 1);
> + if (*Path == NULL) {
> + FreePool(*Drive);
> + return EFI_OUT_OF_RESOURCES;
> + }
> + }
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> Function for 'cd' command.
>
> @param[in] ImageHandle Handle to the Image (NULL if Internal).
> @@ -31,23 +181,26 @@ ShellCommandRunCd (
> {
> EFI_STATUS Status;
> LIST_ENTRY *Package;
> - CONST CHAR16 *Directory;
> - CHAR16 *Cwd;
> + CONST CHAR16 *Cwd;
> CHAR16 *Path;
> CHAR16 *Drive;
> - UINTN CwdSize;
> - UINTN DriveSize;
> CHAR16 *ProblemParam;
> SHELL_STATUS ShellStatus;
> - SHELL_FILE_HANDLE Handle;
> CONST CHAR16 *Param1;
> CHAR16 *Param1Copy;
> - CHAR16* Walker;
> + CHAR16 *Walker;
> + CHAR16 *Splitter;
> + CHAR16 *TempBuffer;
> + UINTN TotalSize;
>
> - ProblemParam = NULL;
> - ShellStatus = SHELL_SUCCESS;
> - Drive = NULL;
> - DriveSize = 0;
> + ProblemParam = NULL;
> + ShellStatus = SHELL_SUCCESS;
> + Cwd = NULL;
> + Path = NULL;
> + Drive = NULL;
> + Splitter = NULL;
> + TempBuffer = NULL;
> + TotalSize = 0;
>
> Status = CommandInit();
> ASSERT_EFI_ERROR(Status);
> @@ -87,194 +240,106 @@ ShellCommandRunCd (
> // else If there are 2 value parameters, then print the error message
> // else If there is 1 value paramerer , then change the directory
> //
> - Param1 = ShellCommandLineGetRawValue(Package, 1);
> - if (Param1 == NULL) {
> - //
> - // display the current directory
> - //
> - Directory = ShellGetCurrentDir(NULL);
> - if (Directory != NULL) {
> - ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_PRINT),
> gShellLevel2HiiHandle, Directory);
> - } else {
> - ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD),
> gShellLevel2HiiHandle, L"cd");
> - ShellStatus = SHELL_NOT_FOUND;
> - }
> + Cwd = ShellGetCurrentDir (NULL);
> + if (Cwd == NULL) {
> + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_GEN_NO_CWD),
> gShellLevel2HiiHandle, L"cd");
> + ShellStatus = SHELL_NOT_FOUND;
> } else {
> - Param1Copy = CatSPrint(NULL, L"%s", Param1, NULL);
> - for (Walker = Param1Copy; Walker != NULL && *Walker != CHAR_NULL ;
> Walker++) {
> - if (*Walker == L'\"') {
> - CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0]));
> + Param1 = ShellCommandLineGetRawValue(Package, 1);
> + if (Param1 == NULL) {
> + //
> + // display the current directory
> + //
> + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_CD_PRINT),
> gShellLevel2HiiHandle, Cwd);
> + } else {
> + Param1Copy = CatSPrint(NULL, L"%s", Param1, NULL);
> + for (Walker = Param1Copy; Walker != NULL && *Walker != CHAR_NULL;
> Walker++) {
> + if (*Walker == L'\"') {
> + CopyMem(Walker, Walker + 1, StrSize(Walker) - sizeof(Walker[0]));
> + }
> }
> - }
> -
> - if (Param1Copy != NULL) {
> - Param1Copy = PathCleanUpDirectories(Param1Copy);
> - }
> - if (Param1Copy != NULL) {
> - if (StrCmp(Param1Copy, L".") == 0) {
> - //
> - // nothing to do... change to current directory
> - //
> - } else if (StrCmp(Param1Copy, L"..") == 0) {
> +
> + if (Param1Copy != NULL && IsCurrentFileSystem (Param1Copy, Cwd)) {
> + Status = ReplaceDriveWithCwd (&Param1Copy,Cwd);
> + if (!EFI_ERROR(Status)) {
> + Param1Copy = PathCleanUpDirectories(Param1Copy);
> + }
> + } else {
> //
> - // Change up one directory...
> + // Can't use cd command to change filesystem.
> //
> - Directory = ShellGetCurrentDir(NULL);
> - if (Directory == NULL) {
> - ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD),
> gShellLevel2HiiHandle, L"cd");
> - ShellStatus = SHELL_NOT_FOUND;
> - } else {
> - CwdSize = StrSize(Directory) + sizeof(CHAR16);
> - Cwd = AllocateZeroPool(CwdSize);
> - if (Cwd == NULL) {
> - ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM),
> gShellLevel2HiiHandle, L"cd");
> - ShellStatus = SHELL_OUT_OF_RESOURCES;
> - } else {
> - StrCpyS (Cwd, StrSize (Directory) / sizeof (CHAR16) + 1, Directory);
> - StrCatS (Cwd, StrSize (Directory) / sizeof (CHAR16) + 1, L"\\");
> - Drive = GetFullyQualifiedPath (Cwd);
> - PathRemoveLastItem (Drive);
> - FreePool (Cwd);
> - }
> - }
> - if (ShellStatus == SHELL_SUCCESS && Drive != NULL) {
> + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CD_NF),
> gShellLevel2HiiHandle, L"cd");
> + Status = EFI_NOT_FOUND;
> + }
> +
> + if (!EFI_ERROR(Status) && Param1Copy != NULL) {
> + Splitter = StrStr (Cwd, L":");
> + if (Param1Copy[0] == L'\\') {
> //
> - // change directory on current drive letter
> + // Absolute Path on current drive letter.
> //
> - Status = gEfiShellProtocol->SetCurDir(NULL, Drive);
> - if (Status == EFI_NOT_FOUND) {
> - ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF),
> gShellLevel2HiiHandle, L"cd");
> - ShellStatus = SHELL_NOT_FOUND;
> + TotalSize = ((Splitter - Cwd + 1) * sizeof(CHAR16)) +
> StrSize(Param1Copy);
> + TempBuffer = AllocateZeroPool(TotalSize);
> + if (TempBuffer == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + } else {
> + StrnCpyS(TempBuffer, TotalSize / sizeof(CHAR16), Cwd, (Splitter -
> Cwd + 1));
> + StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), Param1Copy);
> +
> + FreePool(Param1Copy);
> + Param1Copy = TempBuffer;
> + TempBuffer = NULL;
> }
> - }
> - } else if (StrCmp(Param1Copy, L"\\") == 0) {
> - //
> - // Move to root of current drive
> - //
> - Directory = ShellGetCurrentDir(NULL);
> - if (Directory == NULL) {
> - ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD),
> gShellLevel2HiiHandle, L"cd");
> - ShellStatus = SHELL_NOT_FOUND;
> } else {
> - CwdSize = StrSize(Directory) + sizeof(CHAR16);
> - Cwd = AllocateZeroPool(CwdSize);
> - if (Cwd == NULL) {
> - ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM),
> gShellLevel2HiiHandle, L"cd");
> - ShellStatus = SHELL_OUT_OF_RESOURCES;
> - } else {
> - StrCpyS (Cwd, StrSize (Directory) / sizeof (CHAR16) + 1, Directory);
> - StrCatS (Cwd, StrSize (Directory) / sizeof (CHAR16) + 1, L"\\");
> - Drive = GetFullyQualifiedPath (Cwd);
> - while (PathRemoveLastItem (Drive)) {
> - //
> - // Check if Drive contains 'fsx:\' only or still points to a sub-directory.
> - // Don't remove trailing '\' from Drive if it points to the root
> directory.
> - //
> - Path = StrStr (Drive, L":\\");
> - if ((Path != NULL) && (*(Path + 2) == CHAR_NULL)) {
> - break;
> - }
> + if (StrStr (Param1Copy,L":") == NULL) {
> + TotalSize = StrSize(Cwd) + StrSize (Param1Copy);
> + TempBuffer = AllocateZeroPool (TotalSize);
> + if (TempBuffer == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + } else {
> + StrCpyS (TempBuffer, TotalSize / sizeof(CHAR16), Cwd);
> + StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), L"\\");
> + StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), Param1Copy);
> +
> + FreePool(Param1Copy);
> + Param1Copy = PathCleanUpDirectories (TempBuffer);
> }
> - FreePool (Cwd);
> }
> }
> - if (ShellStatus == SHELL_SUCCESS && Drive != NULL) {
> - //
> - // change directory on current drive letter
> - //
> - Status = gEfiShellProtocol->SetCurDir(NULL, Drive);
> - if (Status == EFI_NOT_FOUND) {
> - ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF),
> gShellLevel2HiiHandle, L"cd");
> - ShellStatus = SHELL_NOT_FOUND;
> - }
> - }
> - } else if (StrStr(Param1Copy, L":") == NULL) {
> - //
> - // change directory without a drive identifier
> - //
> - if (ShellGetCurrentDir(NULL) == NULL) {
> - ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD),
> gShellLevel2HiiHandle, L"cd");
> + }
> +
> + if (!EFI_ERROR(Status)) {
> + Status = ExtractDriveAndPath(Param1Copy, &Drive, &Path);
> + }
> +
> + if (!EFI_ERROR(Status) && Drive != NULL && Path != NULL) {
> + if (EFI_ERROR(ShellIsDirectory(Param1Copy))) {
> + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_GEN_NOT_DIR),
> gShellLevel2HiiHandle, L"cd", Param1Copy);
> ShellStatus = SHELL_NOT_FOUND;
> } else {
> - ASSERT((Drive == NULL && DriveSize == 0) || (Drive != NULL));
> - Drive = StrnCatGrow(&Drive, &DriveSize, ShellGetCurrentDir(NULL),
> 0);
> - Drive = StrnCatGrow(&Drive, &DriveSize, L"\\", 0);
> - if (*Param1Copy == L'\\') {
> - while (PathRemoveLastItem(Drive)) ;
> - Drive = StrnCatGrow(&Drive, &DriveSize, Param1Copy+1, 0);
> - } else {
> - Drive = StrnCatGrow(&Drive, &DriveSize, Param1Copy, 0);
> - }
> - //
> - // Verify that this is a valid directory
> - //
> - Status = gEfiShellProtocol->OpenFileByName(Drive, &Handle,
> EFI_FILE_MODE_READ);
> + Status = gEfiShellProtocol->SetCurDir(Drive, Path + 1);
> if (EFI_ERROR(Status)) {
> - ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF),
> gShellLevel2HiiHandle, L"cd", Drive);
> - ShellStatus = SHELL_NOT_FOUND;
> - } else if (EFI_ERROR(FileHandleIsDirectory(Handle))) {
> - ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR),
> gShellLevel2HiiHandle, L"cd", Drive);
> - ShellStatus = SHELL_NOT_FOUND;
> - }
> - if (ShellStatus == SHELL_SUCCESS && Drive != NULL) {
> - //
> - // change directory on current drive letter
> - //
> - Status = gEfiShellProtocol->SetCurDir(NULL, Drive);
> - if (Status == EFI_NOT_FOUND) {
> - ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF),
> gShellLevel2HiiHandle, L"cd");
> - ShellStatus = SHELL_NOT_FOUND;
> - }
> - }
> - if (Handle != NULL) {
> - gEfiShellProtocol->CloseFile(Handle);
> - DEBUG_CODE(Handle = NULL;);
> - }
> - }
> - } else {
> - //
> - // change directory with a drive letter
> - //
> - Drive = AllocateCopyPool(StrSize(Param1Copy), Param1Copy);
> - if (Drive == NULL) {
> - ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM),
> gShellLevel2HiiHandle, L"cd");
> - ShellStatus = SHELL_OUT_OF_RESOURCES;
> - } else {
> - Path = StrStr(Drive, L":");
> - ASSERT(Path != NULL);
> - if (EFI_ERROR(ShellIsDirectory(Param1Copy))) {
> - ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR),
> gShellLevel2HiiHandle, L"cd", Param1Copy);
> - ShellStatus = SHELL_NOT_FOUND;
> - } else if (*(Path+1) == CHAR_NULL) {
> - ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF),
> gShellLevel2HiiHandle, L"cd");
> + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_GEN_DIR_NF),
> gShellLevel2HiiHandle, L"cd", Param1Copy);
> ShellStatus = SHELL_NOT_FOUND;
> } else {
> - *(Path+1) = CHAR_NULL;
> - if (Path == Drive + StrLen(Drive)) {
> - ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF),
> gShellLevel2HiiHandle, L"cd");
> - ShellStatus = SHELL_NOT_FOUND;
> - } else {
> - Status = gEfiShellProtocol->SetCurDir(Drive, Path+2);
> - ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_PRINT),
> gShellLevel2HiiHandle, ShellGetCurrentDir(Drive));
> - }
> - }
> - if (Status == EFI_NOT_FOUND) {
> - ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF),
> gShellLevel2HiiHandle, L"cd");
> - Status = SHELL_NOT_FOUND;
> - } else if (EFI_ERROR(Status)) {
> - ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF),
> gShellLevel2HiiHandle, L"cd", Param1Copy);
> - Status = SHELL_NOT_FOUND;
> + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_CD_PRINT),
> gShellLevel2HiiHandle, ShellGetCurrentDir(Drive));
> }
> }
> }
> +
> + if (Drive != NULL) {
> + FreePool (Drive);
> + }
> +
> + if (Path != NULL) {
> + FreePool (Path);
> + }
> +
> + FreePool(Param1Copy);
> }
> - FreePool(Param1Copy);
> }
> }
>
> - if (Drive != NULL) {
> - FreePool(Drive);
> - }
> //
> // free the command line package
> //
> --
> 2.9.0.windows.1
next prev parent reply other threads:[~2016-12-21 16:23 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-12-21 8:54 [PATCH 0/2] ShellPkg/cd: Fix "cd" to support "fs0:dir" (no slash after ':') Ruiyu Ni
2016-12-21 8:55 ` [PATCH 1/2] MdePkg/BaseLib: Fix PathCleanUpDirectories to correctly handle "\.\" Ruiyu Ni
2016-12-21 8:55 ` [PATCH 2/2] ShellPkg/cd: Fix "cd" to support "fs0:dir" (no slash after ':') Ruiyu Ni
2016-12-21 16:23 ` Carsey, Jaben [this message]
2016-12-23 5:43 ` Ni, Ruiyu
2016-12-27 23:01 ` Carsey, Jaben
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=CB6E33457884FA40993F35157061515C54B2D5A2@FMSMSX103.amr.corp.intel.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