From f42974dd9a7d0ea690d293f88396abd289f0014c Mon Sep 17 00:00:00 2001 From: Nigel Croxon Date: Fri, 8 Aug 2014 15:21:16 -0400 Subject: [PATCH] From: David Decotigny Date: Thu, 31 Jul 2014 13:42:23 -0700 Subject: [PATCH 4/4] Use Shell protocols to retrieve argc/argv, when available. New header files efishellintf.h efishellparm.h are coming from EDK II, initial location and license at top of files. Only modifications: - efishellintf.h: s/EFI_FILE_PROTOCOL/EFI_FILE/ + expand BITx macros (1< Signed-off-by: Nigel Croxon --- gnu-efi-3.0/apps/Makefile | 2 +- gnu-efi-3.0/apps/t8.c | 19 +++++++ gnu-efi-3.0/inc/efishellintf.h | 94 ++++++++++++++++++++++++++++++++++ gnu-efi-3.0/inc/efishellparm.h | 63 +++++++++++++++++++++++ gnu-efi-3.0/lib/cmdline.c | 56 +++++++++++++++++++- 5 files changed, 232 insertions(+), 2 deletions(-) create mode 100644 gnu-efi-3.0/apps/t8.c create mode 100644 gnu-efi-3.0/inc/efishellintf.h create mode 100644 gnu-efi-3.0/inc/efishellparm.h diff --git a/gnu-efi-3.0/apps/Makefile b/gnu-efi-3.0/apps/Makefile index 5a91289..64c38e1 100644 --- a/gnu-efi-3.0/apps/Makefile +++ b/gnu-efi-3.0/apps/Makefile @@ -61,7 +61,7 @@ LOADLIBES += -T $(LDSCRIPT) FORMAT = efi-app-$(ARCH) TARGET_APPS = t.efi t2.efi t3.efi t4.efi t5.efi t6.efi \ - printenv.efi t7.efi tcc.efi modelist.efi \ + printenv.efi t7.efi t8.efi tcc.efi modelist.efi \ route80h.efi drv0_use.efi AllocPages.efi \ FreePages.efi TARGET_BSDRIVERS = drv0.efi diff --git a/gnu-efi-3.0/apps/t8.c b/gnu-efi-3.0/apps/t8.c new file mode 100644 index 0000000..10f8811 --- /dev/null +++ b/gnu-efi-3.0/apps/t8.c @@ -0,0 +1,19 @@ +#include +#include + +EFI_STATUS +efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) +{ + INTN Argc, i; + CHAR16 **Argv; + + InitializeLib(ImageHandle, SystemTable); + Argc = GetShellArgcArgv(ImageHandle, &Argv); + + Print(L"Hello World, started with Argc=%d\n", Argc); + for (i = 0 ; i < Argc ; ++i) + Print(L" Argv[%d] = '%s'\n", i, Argv[i]); + + Print(L"Bye.\n"); + return EFI_SUCCESS; +} diff --git a/gnu-efi-3.0/inc/efishellintf.h b/gnu-efi-3.0/inc/efishellintf.h new file mode 100644 index 0000000..e649acd --- /dev/null +++ b/gnu-efi-3.0/inc/efishellintf.h @@ -0,0 +1,94 @@ +/** @file + SHELL_INTERFACE_PROTOCOL from EDK shell (no spec). + + Shell Interface - additional information (over image_info) provided + to an application started by the shell. + + ConIo provides a file-style interface to the console. + + The shell interface's and data (including ConIo) are only valid during + the applications Entry Point. Once the application returns from it's + entry point the data is freed by the invoking shell. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ 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 + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/* + * This is based on ShellPkg/Include/Protocol/EfiShellInterface.h from EDK II. + */ + +#ifndef _SHELLINTERFACE_H_ +#define _SHELLINTERFACE_H_ + + +#define SHELL_INTERFACE_PROTOCOL_GUID \ + { \ + 0x47c7b223, 0xc42a, 0x11d2, {0x8e, 0x57, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} \ + } + +/// +/// Bit definitions for EFI_SHELL_ARG_INFO +/// +typedef enum { + ARG_NO_ATTRIB = 0x0, + ARG_IS_QUOTED = 1<<0, + ARG_PARTIALLY_QUOTED = 1<<1, + ARG_FIRST_HALF_QUOTED = 1<<2, + ARG_FIRST_CHAR_IS_ESC = 1<<3 +} EFI_SHELL_ARG_INFO_TYPES; + +/// +/// Attributes for an argument. +/// +typedef struct _EFI_SHELL_ARG_INFO { + UINT32 Attributes; +} EFI_SHELL_ARG_INFO; + +/// +/// This protocol provides access to additional information about a shell application. +/// +typedef struct { + /// + /// Handle back to original image handle & image information. + /// + EFI_HANDLE ImageHandle; + EFI_LOADED_IMAGE *Info; + + /// + /// Parsed arg list converted more C-like format. + /// + CHAR16 **Argv; + UINTN Argc; + + /// + /// Storage for file redirection args after parsing. + /// + CHAR16 **RedirArgv; + UINTN RedirArgc; + + /// + /// A file style handle for console io. + /// + EFI_FILE *StdIn; + EFI_FILE *StdOut; + EFI_FILE *StdErr; + + /// + /// List of attributes for each argument. + /// + EFI_SHELL_ARG_INFO *ArgInfo; + + /// + /// Whether we are echoing. + /// + BOOLEAN EchoOn; +} EFI_SHELL_INTERFACE; + +#endif diff --git a/gnu-efi-3.0/inc/efishellparm.h b/gnu-efi-3.0/inc/efishellparm.h new file mode 100644 index 0000000..da120e5 --- /dev/null +++ b/gnu-efi-3.0/inc/efishellparm.h @@ -0,0 +1,63 @@ +/** @file + EFI_SHELL_PARAMETERS_PROTOCOL as defined in the UEFI Shell 2.0 specification. + + Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+ 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 + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/* + * This is based on ShellPkg/Include/Protocol/EfiShellParameters.h from EDK II. + */ + +#ifndef __EFI_SHELL_PARAMETERS_PROTOCOL__ +#define __EFI_SHELL_PARAMETERS_PROTOCOL__ + + +// EDK2's ShellBase.h +typedef VOID *SHELL_FILE_HANDLE; + +#define EFI_SHELL_PARAMETERS_PROTOCOL_GUID \ + { \ + 0x752f3136, 0x4e16, 0x4fdc, { 0xa2, 0x2a, 0xe5, 0xf4, 0x68, 0x12, 0xf4, 0xca } \ + } + +typedef struct _EFI_SHELL_PARAMETERS_PROTOCOL { + /// + /// Points to an Argc-element array of points to NULL-terminated strings containing + /// the command-line parameters. The first entry in the array is always the full file + /// path of the executable. Any quotation marks that were used to preserve + /// whitespace have been removed. + /// + CHAR16 **Argv; + + /// + /// The number of elements in the Argv array. + /// + UINTN Argc; + + /// + /// The file handle for the standard input for this executable. This may be different + /// from the ConInHandle in EFI_SYSTEM_TABLE. + /// + SHELL_FILE_HANDLE StdIn; + + /// + /// The file handle for the standard output for this executable. This may be different + /// from the ConOutHandle in EFI_SYSTEM_TABLE. + /// + SHELL_FILE_HANDLE StdOut; + + /// + /// The file handle for the standard error output for this executable. This may be + /// different from the StdErrHandle in EFI_SYSTEM_TABLE. + /// + SHELL_FILE_HANDLE StdErr; +} EFI_SHELL_PARAMETERS_PROTOCOL; + +#endif diff --git a/gnu-efi-3.0/lib/cmdline.c b/gnu-efi-3.0/lib/cmdline.c index 1392b0e..abbaec4 100644 --- a/gnu-efi-3.0/lib/cmdline.c +++ b/gnu-efi-3.0/lib/cmdline.c @@ -1,5 +1,9 @@ #include "lib.h" +#include "efiprot.h" +#include "efishellintf.h" +#include "efishellparm.h" + #ifndef MAX_ARGV_CONTENTS_SIZE # define MAX_CMDLINE_SIZE 1024 #endif @@ -19,8 +23,9 @@ For safety, we support the trailing \0 without a space before, as well as several consecutive spaces (-> several args). */ +static INTN -GetShellArgcArgv( +GetShellArgcArgvFromLoadedImage( EFI_HANDLE ImageHandle, CHAR16 **ResultArgv[] ) @@ -62,6 +67,55 @@ GetShellArgcArgv( if ((*ArgStart != L'\0') && (Argc < MAX_CMDLINE_ARGC)) Argv[Argc++] = ArgStart; + // Print(L"Got argc/argv from loaded image proto\n"); *ResultArgv = Argv; return Argc; } + +INTN GetShellArgcArgv(EFI_HANDLE ImageHandle, CHAR16 **Argv[]) +{ + // Code inspired from EDK2's + // ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c (BSD) + EFI_STATUS Status; + static const EFI_GUID EfiShellParametersProtocolGuid + = EFI_SHELL_PARAMETERS_PROTOCOL_GUID; + static const EFI_GUID ShellInterfaceProtocolGuid + = SHELL_INTERFACE_PROTOCOL_GUID; + EFI_SHELL_PARAMETERS_PROTOCOL *EfiShellParametersProtocol = NULL; + EFI_SHELL_INTERFACE *EfiShellInterfaceProtocol = NULL; + + Status = uefi_call_wrapper(BS->OpenProtocol, 6, + ImageHandle, + &EfiShellParametersProtocolGuid, + (VOID **)&EfiShellParametersProtocol, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR(Status)) + { + // use shell 2.0 interface + // Print(L"Got argc/argv from shell intf proto\n"); + *Argv = EfiShellParametersProtocol->Argv; + return EfiShellParametersProtocol->Argc; + } + + // try to get shell 1.0 interface instead. + Status = uefi_call_wrapper(BS->OpenProtocol, 6, + ImageHandle, + &ShellInterfaceProtocolGuid, + (VOID **)&EfiShellInterfaceProtocol, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR(Status)) + { + // Print(L"Got argc/argv from shell params proto\n"); + *Argv = EfiShellInterfaceProtocol->Argv; + return EfiShellInterfaceProtocol->Argc; + } + + // shell 1.0 and 2.0 interfaces failed + return GetShellArgcArgvFromLoadedImage(ImageHandle, Argv); +}