From 3e2b20a1ad4b777d2834075bcd9a38f364e42c99 Mon Sep 17 00:00:00 2001 From: Brendan Jackman Date: Tue, 11 Feb 2014 22:45:18 +0000 Subject: [PATCH] ShellPkg: Make Argv[0] the full file path of the command Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brendan Jackman Reviewed-by: Olivier Martin Reviewed-by: Jaben Carsey git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15223 6f19259b-4bc3-4df7-8a09-765794883524 --- ShellPkg/Application/Shell/ShellProtocol.c | 36 ++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/ShellPkg/Application/Shell/ShellProtocol.c b/ShellPkg/Application/Shell/ShellProtocol.c index 9260d9b021..5027137705 100644 --- a/ShellPkg/Application/Shell/ShellProtocol.c +++ b/ShellPkg/Application/Shell/ShellProtocol.c @@ -1396,6 +1396,7 @@ InternalShellExecuteDevicePath( EFI_SHELL_PARAMETERS_PROTOCOL ShellParamsProtocol; UINTN InternalExitDataSize; UINTN *ExitDataSizePtr; + CHAR16 *ImagePath; // ExitDataSize is not OPTIONAL for gBS->BootServices, provide somewhere for // it to be dumped if the caller doesn't want it. @@ -1464,6 +1465,33 @@ InternalShellExecuteDevicePath( ShellParamsProtocol.StdErr = ShellInfoObject.NewShellParametersProtocol->StdErr; Status = UpdateArgcArgv(&ShellParamsProtocol, CommandLine, NULL, NULL); ASSERT_EFI_ERROR(Status); + // + // Replace Argv[0] with the full path of the binary we're executing: + // If the command line was "foo", the binary might be called "foo.efi". + // "The first entry in [Argv] is always the full file path of the + // executable" - UEFI Shell Spec section 2.3 + // + ImagePath = EfiShellGetFilePathFromDevicePath (DevicePath); + // The image we're executing isn't necessarily in a filesystem - it might + // be memory mapped. In this case EfiShellGetFilePathFromDevicePath will + // return NULL, and we'll leave Argv[0] as UpdateArgcArgv set it. + if (ImagePath != NULL) { + if (ShellParamsProtocol.Argv == NULL) { + // Command line was empty or null. + // (UpdateArgcArgv sets Argv to NULL when CommandLine is "" or NULL) + ShellParamsProtocol.Argv = AllocatePool (sizeof (CHAR16 *)); + if (ShellParamsProtocol.Argv == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Cleanup; + } + ShellParamsProtocol.Argc = 1; + } else { + // Free the string UpdateArgcArgv put in Argv[0]; + FreePool (ShellParamsProtocol.Argv[0]); + } + ShellParamsProtocol.Argv[0] = ImagePath; + } + Status = gBS->InstallProtocolInterface(&NewHandle, &gEfiShellParametersProtocolGuid, EFI_NATIVE_INTERFACE, &ShellParamsProtocol); ASSERT_EFI_ERROR(Status); @@ -1706,6 +1734,7 @@ EfiShellRemoveDupInFileList( { EFI_SHELL_FILE_INFO *ShellFileListItem; EFI_SHELL_FILE_INFO *ShellFileListItem2; + EFI_SHELL_FILE_INFO *TempNode; if (FileList == NULL || *FileList == NULL) { return (EFI_INVALID_PARAMETER); @@ -1723,8 +1752,15 @@ EfiShellRemoveDupInFileList( (CHAR16*)ShellFileListItem->FullName, (CHAR16*)ShellFileListItem2->FullName) == 0 ){ + TempNode = (EFI_SHELL_FILE_INFO *)GetPreviousNode( + &(*FileList)->Link, + &ShellFileListItem2->Link + ); RemoveEntryList(&ShellFileListItem2->Link); InternalFreeShellFileInfoNode(ShellFileListItem2); + // Set ShellFileListItem2 to PreviousNode so we don't access Freed + // memory in GetNextNode in the loop expression above. + ShellFileListItem2 = TempNode; } } } -- 2.39.2