From: "Vladimir Olovyannikov" <vladimir.olovyannikov@broadcom.com>
To: "Gao, Zhichao" <zhichao.gao@intel.com>, devel@edk2.groups.io
Cc: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>,
Maciej Rabeda <maciej.rabeda@linux.intel.com>,
"Wu, Jiaxin" <jiaxin.wu@intel.com>,
"Fu, Siyuan" <siyuan.fu@intel.com>, "Ni, Ray" <ray.ni@intel.com>,
"Gao, Liming" <liming.gao@intel.com>, Nd <nd@arm.com>
Subject: Re: [edk2-devel] [PATCH v2 1/1] ShellPkg/DynamicCommand: add HttpDynamicCommand
Date: Thu, 2 Jul 2020 20:47:19 -0700 [thread overview]
Message-ID: <8d65606f6a71a40624ab22868b743530@mail.gmail.com> (raw)
In-Reply-To: <DM6PR11MB44255E2CD6D51095D2F66777F66D0@DM6PR11MB4425.namprd11.prod.outlook.com>
Hi Zhichao,
Thank you for reviewing the patch.
I will send v3 tomorrow addressing formatting and variable scope issues.
Thank you,
Vladimir
-----Original Message-----
From: Gao, Zhichao <zhichao.gao@intel.com>
Sent: Wednesday, July 1, 2020 10:55 PM
To: devel@edk2.groups.io; vladimir.olovyannikov@broadcom.com
Cc: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>; Maciej Rabeda
<maciej.rabeda@linux.intel.com>; Wu, Jiaxin <jiaxin.wu@intel.com>; Fu,
Siyuan <siyuan.fu@intel.com>; Ni, Ray <ray.ni@intel.com>; Gao, Liming
<liming.gao@intel.com>; Nd <nd@arm.com>
Subject: RE: [edk2-devel] [PATCH v2 1/1] ShellPkg/DynamicCommand: add
HttpDynamicCommand
Hi,
Sorry for the delay. As I said in the V1, the patch required the
NetworkPkg maintainers' help to review the network connection
implementation part.
Some comments below.
1. for function RunHttp:
'''
UINTN StartSize;
CHAR16 *Walker;
CHAR16 *VStr;
'''
The above variable is block scope which is strongly discouraged. See
CSS_2_1_Draft Section 5.4.1.1.
2. Some indentations need adjust:
a) GetResponse function body
b) "if (!gHttpError) {" section of GetResponse
c) " ValueStr = ShellCommandLineGetValue (CheckPackage, L"-s");" the if
section below this statement
Thanks,
Zhichao
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Vladimir
> Olovyannikov via groups.io
> Sent: Tuesday, May 12, 2020 2:03 AM
> To: devel@edk2.groups.io
> Cc: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>; Samer
El-
> Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>; Gao, Zhichao
> <zhichao.gao@intel.com>; Maciej Rabeda <maciej.rabeda@linux.intel.com>;
Wu,
> Jiaxin <jiaxin.wu@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>; Ni, Ray
> <ray.ni@intel.com>; Gao, Liming <liming.gao@intel.com>; Nd <nd@arm.com>
> Subject: [edk2-devel] [PATCH v2 1/1] ShellPkg/DynamicCommand: add
> HttpDynamicCommand
>
> Introduce an http client utilizing EDK2 HTTP protocol, to
> allow fast image downloading from http/https servers.
> HTTP download speed is usually faster than tftp.
> The client is based on the same approach as tftp dynamic command, and
> uses the same UEFI Shell command line parameters. This makes it easy
> integrating http into existing UEFI Shell scripts.
> Note that to enable HTTP download, feature Pcd
> gEfiNetworkPkgTokenSpaceGuid.PcdAllowHttpConnections must
> be set to TRUE.
>
> Signed-off-by: Vladimir Olovyannikov
<vladimir.olovyannikov@broadcom.com>
> Tested-By: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>
> Cc: Zhichao Gao <zhichao.gao@intel.com>
> Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
> Cc: Jiaxin Wu <jiaxin.wu@intel.com>
> Cc: Siyuan Fu <siyuan.fu@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Nd <nd@arm.com>
> ---
> .../DynamicCommand/HttpDynamicCommand/Http.c | 1701
> +++++++++++++++++
> .../DynamicCommand/HttpDynamicCommand/Http.h | 84 +
> .../HttpDynamicCommand/Http.uni | 113 ++
> .../HttpDynamicCommand/HttpApp.c | 53 +
> .../HttpDynamicCommand/HttpApp.inf | 58 +
> .../HttpDynamicCommand/HttpDynamicCommand.c | 134 ++
> .../HttpDynamicCommand/HttpDynamicCommand.inf | 63 +
> ShellPkg/Include/Guid/ShellLibHiiGuid.h | 5 +
> ShellPkg/ShellPkg.dec | 1 +
> ShellPkg/ShellPkg.dsc | 5 +
> 10 files changed, 2217 insertions(+)
> create mode 100644 ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c
> create mode 100644
> ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h
> create mode 100644
> ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni
> create mode 100644
> ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c
> create mode 100644
> ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
> create mode 100644
> ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.c
> create mode 100644
> ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf
>
> diff --git a/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c
> b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c
> new file mode 100644
> index 000000000000..7238cc6a07cc
> --- /dev/null
> +++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c
> @@ -0,0 +1,1701 @@
> +/** @file
>
> + The implementation for the 'http' Shell command.
>
> +
>
> + Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
>
> + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
<BR>
>
> + (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
>
> + Copyright (c) 2020, Broadcom. All rights reserved. <BR>
>
> +
>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +**/
>
> +
>
> +#include "Http.h"
>
> +
>
> +#define IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH 32
>
> +EFI_HII_HANDLE mHttpHiiHandle;
>
> +
>
> +/*
>
> + Constant strings and definitions related to the message
>
> + indicating the amount of progress in the dowloading of a HTTP file.
>
> +*/
>
> +
>
> +// Number of steps in the progression slider
>
> +#define HTTP_PROGRESS_SLIDER_STEPS \
>
> + ((sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) - 3)
>
> +
>
> +// Size in number of characters plus one (final zero) of the message to
>
> +// indicate the progress of an HTTP download. The format is "[(progress
slider:
>
> +// 40 characters)] (nb of KBytes downloaded so far: 7 characters) Kb".
There
>
> +// are thus the number of characters in HTTP_PROGR_FRAME[] plus 11
> characters
>
> +// (2 // spaces, "Kb" and seven characters for the number of KBytes).
>
> +#define HTTP_PROGRESS_MESSAGE_SIZE \
>
> + ((sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) + 12)
>
> +
>
> +//
>
> +// Buffer size. Note that larger buffer does not mean better speed!
>
> +//
>
> +#define DEFAULT_BUF_SIZE SIZE_32KB
>
> +#define MAX_BUF_SIZE SIZE_4MB
>
> +
>
> +#define MIN_PARAM_COUNT 2
>
> +#define MAX_PARAM_COUNT 4
>
> +
>
> +#define TIMER_MAX_TIMEOUT_S 10
>
> +
>
> +// File name to use when URI ends with "/"
>
> +#define DEFAULT_HTML_FILE L"index.html"
>
> +#define DEFAULT_HTTP_PROTO L"http"
>
> +
>
> +// String to delete the HTTP progress message to be able to update it :
>
> +// (HTTP_PROGRESS_MESSAGE_SIZE-1) '\b'
>
> +#define HTTP_PROGRESS_DEL \
>
> +
L"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\
>
> +\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
>
> +
>
> +#define HTTP_KB L"\b\b\b\b\b\b\b\b\b\b"
>
> +// Frame for the progression slider
>
> +#define HTTP_PROGR_FRAME L"[
]"
>
> +
>
> +// String descriptions for server errors
>
> +STATIC CONST CHAR16 *ErrStatusDesc[] =
>
> +{
>
> + L"400 Bad Request",
>
> + L"401 Unauthorized",
>
> + L"402 Payment required",
>
> + L"403 Forbidden",
>
> + L"404 Not Found",
>
> + L"405 Method not allowed",
>
> + L"406 Not acceptable",
>
> + L"407 Proxy authentication required",
>
> + L"408 Request time out",
>
> + L"409 Conflict",
>
> + L"410 Gone",
>
> + L"411 Length required",
>
> + L"412 Precondition failed",
>
> + L"413 Request entity too large",
>
> + L"414 Request URI to large",
>
> + L"415 Unsupported media type",
>
> + L"416 Requested range not satisfied",
>
> + L"417 Expectation failed",
>
> + L"500 Internal server error",
>
> + L"501 Not implemented",
>
> + L"502 Bad gateway",
>
> + L"503 Service unavailable",
>
> + L"504 Gateway timeout",
>
> + L"505 HTTP version not supported"
>
> +};
>
> +
>
> +// Local File Handle
>
> +STATIC SHELL_FILE_HANDLE mFileHandle = NULL;
>
> +
>
> +// Path of the local file, Unicode encoded
>
> +STATIC CONST CHAR16 *mLocalFilePath;
>
> +
>
> +STATIC BOOLEAN gRequestCallbackComplete = FALSE;
>
> +STATIC BOOLEAN gResponseCallbackComplete = FALSE;
>
> +
>
> +STATIC BOOLEAN gHttpError;
>
> +
>
> +/**
>
> + Cleans off leading and trailing spaces and tabs.
>
> +
>
> + @param[in] String pointer to the string to trim them off.
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +TrimSpaces (
>
> + IN CHAR16 **String
>
> + )
>
> +{
>
> + ASSERT(String != NULL);
>
> + ASSERT(*String!= NULL);
>
> + //
>
> + // Remove any spaces and tabs at the beginning of the (*String).
>
> + //
>
> + while (((*String)[0] == L' ') || ((*String)[0] == L'\t')) {
>
> + CopyMem (
>
> + (*String),
>
> + (*String) + 1,
>
> + StrSize ((*String)) - sizeof((*String)[0])
>
> + );
>
> + }
>
> +
>
> + //
>
> + // Remove any spaces and tabs at the end of the (*String).
>
> + //
>
> + while ((StrLen (*String) > 0) &&
>
> + (((*String)[StrLen ((*String)) - 1] == L' ') ||
>
> + ((*String)[StrLen ((*String)) - 1] == L'\t'))
>
> + ) {
>
> + (*String)[StrLen ((*String)) - 1] = CHAR_NULL;
>
> + }
>
> +
>
> + return (EFI_SUCCESS);
>
> +}
>
> +
>
> +
>
> +/*
>
> + * Callbacks for request and response.
>
> + * We just acknowledge that operation has completed here.
>
> + */
>
> +STATIC
>
> +VOID
>
> +EFIAPI
>
> +RequestCallback (
>
> + IN EFI_EVENT Event,
>
> + IN VOID *Context
>
> +)
>
> +{
>
> + gRequestCallbackComplete = TRUE;
>
> +}
>
> +
>
> +STATIC
>
> +VOID
>
> +EFIAPI
>
> +ResponseCallback (
>
> + IN EFI_EVENT Event,
>
> + IN VOID *Context
>
> +)
>
> +{
>
> + gResponseCallbackComplete = TRUE;
>
> +}
>
> +
>
> +
>
> +/**
>
> + Check and convert the UINT16 option values of the 'http' command
>
> +
>
> + @param[in] ValueStr Value as an Unicode encoded string
>
> + @param[out] Value UINT16 value
>
> +
>
> + @return TRUE The value was returned.
>
> + @return FALSE A parsing error occured.
>
> +**/
>
> +STATIC
>
> +BOOLEAN
>
> +StringToUint16 (
>
> + IN CONST CHAR16 *ValueStr,
>
> + OUT UINT16 *Value
>
> + );
>
> +
>
> +/**
>
> + Get the name of the NIC.
>
> +
>
> + @param[in] ControllerHandle The network physical device handle.
>
> + @param[in] NicNumber The network physical device number.
>
> + @param[out] NicName Address where to store the NIC name.
>
> + The memory area has to be at least
>
> + IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH
>
> + double byte wide.
>
> +
>
> + @return EFI_SUCCESS The name of the NIC was returned.
>
> + @return Others The creation of the child for the Managed
>
> + Network Service failed or the opening of
>
> + the Managed Network Protocol failed or
>
> + the operational parameters for the
>
> + Managed Network Protocol could not be
>
> + read.
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +GetNicName (
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN UINTN NicNumber,
>
> + OUT CHAR16 *NicName
>
> + );
>
> +
>
> +/**
>
> + Create a child for the service identified by its service binding
protocol GUID
>
> + and get from the child the interface of the protocol identified by
its GUID.
>
> +
>
> + @param[in] ControllerHandle Controller handle.
>
> + @param[in] ServiceBindingProtocolGuid Service binding protocol
GUID of the
>
> + service to be created.
>
> + @param[in] ProtocolGuid GUID of the protocol to be
open.
>
> + @param[out] ChildHandle Address where the handler of
the
>
> + created child is returned.
NULL is
>
> + returned in case of error.
>
> + @param[out] Interface Address where a pointer to
the
>
> + protocol interface is
returned in
>
> + case of success.
>
> +
>
> + @return EFI_SUCCESS The child was created and the protocol opened.
>
> + @return Others Either the creation of the child or the opening
>
> + of the protocol failed.
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +CreateServiceChildAndOpenProtocol (
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN EFI_GUID *ServiceBindingProtocolGuid,
>
> + IN EFI_GUID *ProtocolGuid,
>
> + OUT EFI_HANDLE *ChildHandle,
>
> + OUT VOID **Interface
>
> + );
>
> +
>
> +/**
>
> + Close the protocol identified by its GUID on the child handle of the
service
>
> + identified by its service binding protocol GUID, then destroy the
child
>
> + handle.
>
> +
>
> + @param[in] ControllerHandle Controller handle.
>
> + @param[in] ServiceBindingProtocolGuid Service binding protocol GUID
of the
>
> + service to be destroyed.
>
> + @param[in] ProtocolGuid GUID of the protocol to be
closed.
>
> + @param[in] ChildHandle Handle of the child to be
destroyed.
>
> +
>
> +**/
>
> +STATIC
>
> +VOID
>
> +CloseProtocolAndDestroyServiceChild (
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN EFI_GUID *ServiceBindingProtocolGuid,
>
> + IN EFI_GUID *ProtocolGuid,
>
> + IN EFI_HANDLE ChildHandle
>
> + );
>
> +
>
> +
>
> +/**
>
> + Worker function that download the data of a file from an HTTP server
given
>
> + the path of the file and its size.
>
> +
>
> + @param[in] Context A pointer to the download context.
>
> +
>
> + @retval EFI_SUCCESS The file was downloaded.
>
> + @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
>
> + @retval Others The downloading of the file
>
> + from the server failed.
>
> +
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +DownloadFile (
>
> + IN DOWNLOAD_CONTEXT *Context
>
> + );
>
> +
>
> +STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
>
> + {L"-i", TypeValue},
>
> + {L"-l", TypeValue},
>
> + {L"-s", TypeValue},
>
> + {L"-t", TypeValue},
>
> + {NULL , TypeMax}
>
> + };
>
> +
>
> +/**
>
> + Function for 'http' command.
>
> +
>
> + @param[in] ImageHandle Handle to the Image (NULL if Internal).
>
> + @param[in] SystemTable Pointer to the System Table (NULL if
Internal).
>
> +
>
> + @return SHELL_SUCCESS The 'http' command completed
successfully.
>
> + @return SHELL_ABORTED The Shell Library initialization
failed.
>
> + @return SHELL_INVALID_PARAMETER At least one of the command's
> arguments is
>
> + not valid.
>
> + @return SHELL_OUT_OF_RESOURCES A memory allocation failed.
>
> + @return SHELL_NOT_FOUND Network Interface Card not found.
>
> + @return SHELL_UNSUPPORTED Command was valid, but the server
> returned
>
> + a status code indicating some
error.
>
> + Examine the file requested for
error body.
>
> +
>
> +**/
>
> +SHELL_STATUS
>
> +RunHttp (
>
> + IN EFI_HANDLE ImageHandle,
>
> + IN EFI_SYSTEM_TABLE *SystemTable
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + LIST_ENTRY *CheckPackage;
>
> + CHAR16 *ProblemParam;
>
> + UINTN ParamCount;
>
> + CONST CHAR16 *UserNicName;
>
> + BOOLEAN NicFound;
>
> + CONST CHAR16 *ValueStr;
>
> + CONST CHAR16 *RemoteFilePath;
>
> + CONST CHAR16 *Walker;
>
> + EFI_HTTP_CONFIG_DATA HttpConfigData;
>
> + EFI_HTTPv4_ACCESS_POINT IPv4Node;
>
> + EFI_HANDLE *Handles;
>
> + UINTN HandleCount;
>
> + UINTN NicNumber;
>
> + UINTN InitialSize;
>
> + UINTN ParamOffset;
>
> + CHAR16
NicName[IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH];
>
> + EFI_HANDLE ControllerHandle;
>
> + EFI_HANDLE HttpChildHandle;
>
> + DOWNLOAD_CONTEXT Context;
>
> +
>
> + ProblemParam = NULL;
>
> + RemoteFilePath = NULL;
>
> + NicFound = FALSE;
>
> + Handles = NULL;
>
> +
>
> + //
>
> + // Initialize the Shell library (we must be in non-auto-init...)
>
> + //
>
> + ParamOffset = 0;
>
> + gHttpError = FALSE;
>
> +
>
> + Status = ShellInitialize ();
>
> + if (EFI_ERROR (Status)) {
>
> + ASSERT_EFI_ERROR (Status);
>
> + return SHELL_ABORTED;
>
> + }
>
> +
>
> + ZeroMem (&Context, sizeof (Context));
>
> +
>
> + //
>
> + // Parse the command line.
>
> + //
>
> + Status = ShellCommandLineParse (
>
> + ParamList,
>
> + &CheckPackage,
>
> + &ProblemParam,
>
> + TRUE);
>
> + if (EFI_ERROR (Status)) {
>
> + if ((Status == EFI_VOLUME_CORRUPTED) &&
>
> + (ProblemParam != NULL) ) {
>
> + ShellPrintHiiEx (
>
> + -1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), mHttpHiiHandle,
>
> + HTTP_APP_NAME, ProblemParam
>
> + );
>
> + SHELL_FREE_NON_NULL (ProblemParam);
>
> + } else {
>
> + ASSERT (FALSE);
>
> + }
>
> +
>
> + goto Error;
>
> + }
>
> +
>
> + //
>
> + // Check the number of parameters
>
> + //
>
> + Status = EFI_INVALID_PARAMETER;
>
> +
>
> + ParamCount = ShellCommandLineGetCount (CheckPackage);
>
> + if (ParamCount > MAX_PARAM_COUNT) {
>
> + ShellPrintHiiEx (
>
> + -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY),
>
> + mHttpHiiHandle, HTTP_APP_NAME
>
> + );
>
> + goto Error;
>
> + }
>
> +
>
> + if (ParamCount < MIN_PARAM_COUNT) {
>
> + ShellPrintHiiEx (
>
> + -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW),
>
> + mHttpHiiHandle, HTTP_APP_NAME
>
> + );
>
> + goto Error;
>
> + }
>
> +
>
> + ZeroMem (&HttpConfigData, sizeof (HttpConfigData));
>
> + ZeroMem (&IPv4Node, sizeof (IPv4Node));
>
> + IPv4Node.UseDefaultAddress = TRUE;
>
> +
>
> + HttpConfigData.HttpVersion = HttpVersion11;
>
> + HttpConfigData.AccessPoint.IPv4Node = &IPv4Node;
>
> +
>
> + //
>
> + // Get the host address (not necessarily IPv4 format)
>
> + //
>
> + ValueStr = ShellCommandLineGetRawValue (CheckPackage, 1);
>
> + if (!ValueStr) {
>
> + ShellPrintHiiEx (
>
> + -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), mHttpHiiHandle,
>
> + HTTP_APP_NAME, ValueStr
>
> + );
>
> + goto Error;
>
> + } else {
>
> + UINTN StartSize;
>
> + CHAR16 *Walker;
>
> + CHAR16 *VStr;
>
> +
>
> + StartSize = 0;
>
> + if (!StrStr (ValueStr, L"://")) {
>
> + Context.ServerAddrAndProto = StrnCatGrow (
>
> + &Context.ServerAddrAndProto,
>
> + &StartSize,
>
> + DEFAULT_HTTP_PROTO,
>
> + StrLen (DEFAULT_HTTP_PROTO)
>
> + );
>
> + Context.ServerAddrAndProto = StrnCatGrow (
>
> + &Context.ServerAddrAndProto,
>
> + &StartSize,
>
> + L"://",
>
> + StrLen (L"://")
>
> + );
>
> + VStr = (CHAR16 *)ValueStr;
>
> + } else {
>
> + VStr = StrStr (ValueStr, L"://") + StrLen (L"://");
>
> + }
>
> +
>
> + for (Walker = VStr; *Walker; Walker++) {
>
> + if (*Walker == L'/') {
>
> + break;
>
> + }
>
> + }
>
> +
>
> + if (*Walker == L'/') {
>
> + ParamOffset = 1;
>
> + RemoteFilePath = Walker;
>
> + }
>
> +
>
> + Context.ServerAddrAndProto = StrnCatGrow (
>
> + &Context.ServerAddrAndProto,
>
> + &StartSize,
>
> + ValueStr,
>
> + StrLen (ValueStr) - StrLen (Walker)
>
> + );
>
> + if (!Context.ServerAddrAndProto) {
>
> + Status = EFI_OUT_OF_RESOURCES;
>
> + goto Error;
>
> + }
>
> + }
>
> +
>
> + if (!RemoteFilePath) {
>
> + RemoteFilePath = ShellCommandLineGetRawValue (CheckPackage, 2);
>
> + if (!RemoteFilePath) {
>
> + // If no path given, assume just "/"
>
> + RemoteFilePath = L"/";
>
> + }
>
> + }
>
> +
>
> + TrimSpaces ((CHAR16 **)&RemoteFilePath);
>
> +
>
> + if (ParamCount == MAX_PARAM_COUNT - ParamOffset) {
>
> + mLocalFilePath = ShellCommandLineGetRawValue (
>
> + CheckPackage,
>
> + MAX_PARAM_COUNT - 1 - ParamOffset);
>
> + } else {
>
> + Walker = RemoteFilePath + StrLen (RemoteFilePath);
>
> + while ((--Walker) >= RemoteFilePath) {
>
> + if ((*Walker == L'\\') ||
>
> + (*Walker == L'/' ) ) {
>
> + break;
>
> + }
>
> + }
>
> +
>
> + mLocalFilePath = Walker + 1;
>
> + }
>
> +
>
> + if (!StrLen (mLocalFilePath)) {
>
> + mLocalFilePath = DEFAULT_HTML_FILE;
>
> + }
>
> +
>
> + InitialSize = 0;
>
> + Context.URI = StrnCatGrow (
>
> + &Context.URI,
>
> + &InitialSize,
>
> + RemoteFilePath,
>
> + StrLen (RemoteFilePath)
>
> + );
>
> + if (!Context.URI) {
>
> + Status = EFI_OUT_OF_RESOURCES;
>
> + goto Error;
>
> + }
>
> +
>
> + //
>
> + // Get the name of the Network Interface Card to be used if any.
>
> + //
>
> + UserNicName = ShellCommandLineGetValue (CheckPackage, L"-i");
>
> +
>
> + ValueStr = ShellCommandLineGetValue (CheckPackage, L"-l");
>
> + if (ValueStr != NULL) {
>
> + if (!StringToUint16 (
>
> + ValueStr,
>
> + &HttpConfigData.AccessPoint.IPv4Node->LocalPort
>
> + )
>
> + ) {
>
> + goto Error;
>
> + }
>
> + }
>
> +
>
> + Context.BufferSize = DEFAULT_BUF_SIZE;
>
> +
>
> + ValueStr = ShellCommandLineGetValue (CheckPackage, L"-s");
>
> + if (ValueStr != NULL) {
>
> + Context.BufferSize = ShellStrToUintn (ValueStr);
>
> + if (!Context.BufferSize || Context.BufferSize > MAX_BUF_SIZE) {
>
> + ShellPrintHiiEx (
>
> + -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
>
> + mHttpHiiHandle, HTTP_APP_NAME, ValueStr
>
> + );
>
> + goto Error;
>
> + }
>
> + }
>
> +
>
> + ValueStr = ShellCommandLineGetValue (CheckPackage, L"-t");
>
> + if (ValueStr != NULL) {
>
> + HttpConfigData.TimeOutMillisec = (UINT32)ShellStrToUintn
(ValueStr);
>
> + }
>
> +
>
> + //
>
> + // Locate all HTTP Service Binding protocols
>
> + //
>
> + Status = gBS->LocateHandleBuffer (
>
> + ByProtocol,
>
> + &gEfiManagedNetworkServiceBindingProtocolGuid,
>
> + NULL,
>
> + &HandleCount,
>
> + &Handles
>
> + );
>
> + if (EFI_ERROR (Status) || (HandleCount == 0)) {
>
> + ShellPrintHiiEx (
>
> + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_NO_NIC), mHttpHiiHandle
>
> + );
>
> + if (!EFI_ERROR (Status)) {
>
> + Status = EFI_NOT_FOUND;
>
> + }
>
> +
>
> + goto Error;
>
> + }
>
> +
>
> + Status = EFI_NOT_FOUND;
>
> +
>
> + for (NicNumber = 0;
>
> + (NicNumber < HandleCount) && (Status != EFI_SUCCESS);
>
> + NicNumber++) {
>
> + ControllerHandle = Handles[NicNumber];
>
> +
>
> + Status = GetNicName (ControllerHandle, NicNumber, NicName);
>
> + if (EFI_ERROR (Status)) {
>
> + ShellPrintHiiEx (
>
> + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_NIC_NAME),
>
> + mHttpHiiHandle, NicNumber, Status
>
> + );
>
> + continue;
>
> + }
>
> +
>
> + if (UserNicName != NULL) {
>
> + if (StrCmp (NicName, UserNicName) != 0) {
>
> + continue;
>
> + }
>
> + NicFound = TRUE;
>
> + }
>
> +
>
> + Status = CreateServiceChildAndOpenProtocol (
>
> + ControllerHandle,
>
> + &gEfiHttpServiceBindingProtocolGuid,
>
> + &gEfiHttpProtocolGuid,
>
> + &HttpChildHandle,
>
> + (VOID**)&Context.Http
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + ShellPrintHiiEx (
>
> + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_OPEN_PROTOCOL),
>
> + mHttpHiiHandle, NicName, Status
>
> + );
>
> + continue;
>
> + }
>
> +
>
> + Status = Context.Http->Configure (Context.Http, &HttpConfigData);
>
> + if (EFI_ERROR (Status)) {
>
> + ShellPrintHiiEx (
>
> + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_CONFIGURE),
>
> + mHttpHiiHandle, NicName, Status
>
> + );
>
> + continue;
>
> + }
>
> +
>
> + Status = DownloadFile (&Context);
>
> +
>
> + ShellPrintHiiEx (
>
> + -1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF), mHttpHiiHandle
>
> + );
>
> +
>
> + CloseProtocolAndDestroyServiceChild (
>
> + ControllerHandle,
>
> + &gEfiHttpServiceBindingProtocolGuid,
>
> + &gEfiHttpProtocolGuid,
>
> + HttpChildHandle
>
> + );
>
> +
>
> + if (EFI_ERROR (Status)) {
>
> + ShellPrintHiiEx (
>
> + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_DOWNLOAD),
>
> + mHttpHiiHandle, RemoteFilePath, NicName, Status
>
> + );
>
> + // If a user aborted the operation, do not try another
controller.
>
> + if (Status == EFI_ABORTED) {
>
> + goto Error;
>
> + }
>
> + }
>
> +
>
> + if (gHttpError) {
>
> + //
>
> + // This is not related to connection, so no need to repeat with
>
> + // another interface.
>
> + //
>
> + break;
>
> + }
>
> + }
>
> +
>
> + if ((UserNicName != NULL) && (!NicFound)) {
>
> + ShellPrintHiiEx (
>
> + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_NIC_NOT_FOUND),
>
> + mHttpHiiHandle, UserNicName
>
> + );
>
> + }
>
> +
>
> +Error:
>
> + ShellCommandLineFreeVarList (CheckPackage);
>
> + SHELL_FREE_NON_NULL (Handles);
>
> + SHELL_FREE_NON_NULL (Context.ServerAddrAndProto);
>
> + SHELL_FREE_NON_NULL (Context.URI);
>
> +
>
> + return Status & ~MAX_BIT;
>
> +}
>
> +
>
> +/**
>
> + Check and convert the UINT16 option values of the 'http' command
>
> +
>
> + @param[in] ValueStr Value as an Unicode encoded string
>
> + @param[out] Value UINT16 value
>
> +
>
> + @return TRUE The value was returned.
>
> + @return FALSE A parsing error occured.
>
> +**/
>
> +STATIC
>
> +BOOLEAN
>
> +StringToUint16 (
>
> + IN CONST CHAR16 *ValueStr,
>
> + OUT UINT16 *Value
>
> + )
>
> +{
>
> + UINTN Val;
>
> +
>
> + Val = ShellStrToUintn (ValueStr);
>
> + if (Val > MAX_UINT16) {
>
> + ShellPrintHiiEx (
>
> + -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
>
> + mHttpHiiHandle, HTTP_APP_NAME, ValueStr
>
> + );
>
> + return FALSE;
>
> + }
>
> +
>
> + *Value = (UINT16)Val;
>
> + return TRUE;
>
> +}
>
> +
>
> +/**
>
> + Get the name of the NIC.
>
> +
>
> + @param[in] ControllerHandle The network physical device handle.
>
> + @param[in] NicNumber The network physical device number.
>
> + @param[out] NicName Address where to store the NIC name.
>
> + The memory area has to be at least
>
> + IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH
>
> + double byte wide.
>
> +
>
> + @return EFI_SUCCESS The name of the NIC was returned.
>
> + @return Others The creation of the child for the Managed
>
> + Network Service failed or the opening of
>
> + the Managed Network Protocol failed or
>
> + the operational parameters for the
>
> + Managed Network Protocol could not be
>
> + read.
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +GetNicName (
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN UINTN NicNumber,
>
> + OUT CHAR16 *NicName
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + EFI_HANDLE MnpHandle;
>
> + EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
>
> + EFI_SIMPLE_NETWORK_MODE SnpMode;
>
> +
>
> + Status = CreateServiceChildAndOpenProtocol (
>
> + ControllerHandle,
>
> + &gEfiManagedNetworkServiceBindingProtocolGuid,
>
> + &gEfiManagedNetworkProtocolGuid,
>
> + &MnpHandle,
>
> + (VOID**)&Mnp
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + goto Error;
>
> + }
>
> +
>
> + Status = Mnp->GetModeData (Mnp, NULL, &SnpMode);
>
> + if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {
>
> + goto Error;
>
> + }
>
> +
>
> + UnicodeSPrint (
>
> + NicName,
>
> + IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH,
>
> + SnpMode.IfType == NET_IFTYPE_ETHERNET ?
>
> + L"eth%d" :
>
> + L"unk%d",
>
> + NicNumber
>
> + );
>
> +
>
> + Status = EFI_SUCCESS;
>
> +
>
> +Error:
>
> +
>
> + if (MnpHandle != NULL) {
>
> + CloseProtocolAndDestroyServiceChild (
>
> + ControllerHandle,
>
> + &gEfiManagedNetworkServiceBindingProtocolGuid,
>
> + &gEfiManagedNetworkProtocolGuid,
>
> + MnpHandle
>
> + );
>
> + }
>
> +
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Create a child for the service identified by its service binding
protocol GUID
>
> + and get from the child the interface of the protocol identified by
its GUID.
>
> +
>
> + @param[in] ControllerHandle Controller handle.
>
> + @param[in] ServiceBindingProtocolGuid Service binding protocol
GUID of the
>
> + service to be created.
>
> + @param[in] ProtocolGuid GUID of the protocol to be
open.
>
> + @param[out] ChildHandle Address where the handler of
the
>
> + created child is returned.
NULL is
>
> + returned in case of error.
>
> + @param[out] Interface Address where a pointer to
the
>
> + protocol interface is
returned in
>
> + case of success.
>
> +
>
> + @return EFI_SUCCESS The child was created and the protocol opened.
>
> + @return Others Either the creation of the child or the opening
>
> + of the protocol failed.
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +CreateServiceChildAndOpenProtocol (
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN EFI_GUID *ServiceBindingProtocolGuid,
>
> + IN EFI_GUID *ProtocolGuid,
>
> + OUT EFI_HANDLE *ChildHandle,
>
> + OUT VOID **Interface
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> +
>
> + *ChildHandle = NULL;
>
> + Status = NetLibCreateServiceChild (
>
> + ControllerHandle,
>
> + gImageHandle,
>
> + ServiceBindingProtocolGuid,
>
> + ChildHandle
>
> + );
>
> + if (!EFI_ERROR (Status)) {
>
> + Status = gBS->OpenProtocol (
>
> + *ChildHandle,
>
> + ProtocolGuid,
>
> + Interface,
>
> + gImageHandle,
>
> + ControllerHandle,
>
> + EFI_OPEN_PROTOCOL_GET_PROTOCOL
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + NetLibDestroyServiceChild (
>
> + ControllerHandle,
>
> + gImageHandle,
>
> + ServiceBindingProtocolGuid,
>
> + *ChildHandle
>
> + );
>
> + *ChildHandle = NULL;
>
> + }
>
> + }
>
> +
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Close the protocol identified by its GUID on the child handle of the
service
>
> + identified by its service binding protocol GUID, then destroy the
child
>
> + handle.
>
> +
>
> + @param[in] ControllerHandle Controller handle.
>
> + @param[in] ServiceBindingProtocolGuid Service binding protocol GUID
of the
>
> + service to be destroyed.
>
> + @param[in] ProtocolGuid GUID of the protocol to be
closed.
>
> + @param[in] ChildHandle Handle of the child to be
destroyed.
>
> +
>
> +**/
>
> +STATIC
>
> +VOID
>
> +CloseProtocolAndDestroyServiceChild (
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN EFI_GUID *ServiceBindingProtocolGuid,
>
> + IN EFI_GUID *ProtocolGuid,
>
> + IN EFI_HANDLE ChildHandle
>
> + )
>
> +{
>
> + gBS->CloseProtocol (
>
> + ChildHandle,
>
> + ProtocolGuid,
>
> + gImageHandle,
>
> + ControllerHandle
>
> + );
>
> +
>
> + NetLibDestroyServiceChild (
>
> + ControllerHandle,
>
> + gImageHandle,
>
> + ServiceBindingProtocolGuid,
>
> + ChildHandle
>
> + );
>
> +}
>
> +
>
> +/**
>
> + Wait until operation completes. Completion is indicated by
>
> + setting of an appropriate variable.
>
> +
>
> + @param[in] Context A pointer to the HTTP download
context.
>
> + @param[in] CallBackComplete A pointer to the callback completion
>
> + variable set by the callback.
>
> +
>
> + @return EFI_SUCCESS Callback signalled completion.
>
> + @return EFI_TIMEOUT Timed out waiting for completion.
>
> + @return Others Error waiting for completion.
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +WaitForCompletion (
>
> + IN DOWNLOAD_CONTEXT *Context,
>
> + IN OUT BOOLEAN *CallBackComplete
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + EFI_EVENT WaitEvt;
>
> +
>
> + Status = EFI_SUCCESS;
>
> +
>
> + // Use a timer to measure timeout. Cannot use Stall here!
>
> + Status = gBS->CreateEvent (
>
> + EVT_TIMER,
>
> + TPL_CALLBACK,
>
> + NULL,
>
> + NULL,
>
> + &WaitEvt
>
> + );
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + if (!EFI_ERROR (Status)) {
>
> + Status = gBS->SetTimer(
>
> + WaitEvt,
>
> + TimerRelative,
>
> + EFI_TIMER_PERIOD_SECONDS (TIMER_MAX_TIMEOUT_S)
>
> + );
>
> +
>
> + ASSERT_EFI_ERROR (Status);
>
> + }
>
> +
>
> + while (! *CallBackComplete &&
>
> + (!EFI_ERROR (Status)) &&
>
> + EFI_ERROR (gBS->CheckEvent (WaitEvt))
>
> + ) {
>
> + Status = Context->Http->Poll (Context->Http);
>
> + }
>
> +
>
> + gBS->SetTimer (WaitEvt, TimerCancel, 0);
>
> + gBS->CloseEvent (WaitEvt);
>
> +
>
> + if (*CallBackComplete) {
>
> + return EFI_SUCCESS;
>
> + }
>
> +
>
> + if (!EFI_ERROR (Status)) {
>
> + Status = EFI_TIMEOUT;
>
> + }
>
> +
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Generate and send a request to the http server.
>
> +
>
> + @param[in] Context HTTP download context.
>
> + @param[in] DownloadUrl Fully qualified URL to be downloaded.
>
> +
>
> + @return EFI_SUCCESS Request has been sent successfully.
>
> + @return EFI_INVALID_PARAMETER Invalid URL.
>
> + @return EFI_OUT_OF_RESOURCES Out of memory.
>
> + @return EFI_DEVICE_ERROR If HTTPS is used, this probably
>
> + means that TLS support either was not
>
> + installed or not configured.
>
> + @return Others Error sending the request.
>
> +**/
>
> +
>
> +STATIC
>
> +EFI_STATUS
>
> +SendRequest (
>
> + IN DOWNLOAD_CONTEXT *Context,
>
> + IN CHAR16 *DownloadUrl
>
> + )
>
> +{
>
> + EFI_HTTP_REQUEST_DATA RequestData;
>
> + EFI_HTTP_HEADER RequestHeader;
>
> + EFI_HTTP_MESSAGE RequestMessage;
>
> + EFI_STATUS Status;
>
> + CHAR16 *Host;
>
> + UINTN StringSize;
>
> +
>
> + ZeroMem (&RequestData, sizeof (RequestData));
>
> + ZeroMem (&RequestHeader, sizeof (RequestHeader));
>
> + ZeroMem (&RequestMessage, sizeof (RequestMessage));
>
> + ZeroMem (&Context->RequestToken, sizeof (Context->RequestToken));
>
> +
>
> + RequestHeader.FieldName = "Host";
>
> +
>
> + Host = (CHAR16 *)Context->ServerAddrAndProto;
>
> + while (*Host != CHAR_NULL && *Host != L'/') {
>
> + Host++;
>
> + }
>
> +
>
> + if (*Host == CHAR_NULL) {
>
> + return EFI_INVALID_PARAMETER;
>
> + }
>
> +
>
> + //
>
> + // Get the next slash
>
> + //
>
> + Host++;
>
> + //
>
> + // And now the host name
>
> + //
>
> + Host++;
>
> +
>
> + StringSize = StrLen (Host) + 1;
>
> + RequestHeader.FieldValue = AllocatePool (StringSize);
>
> + if (!RequestHeader.FieldValue) {
>
> + return EFI_OUT_OF_RESOURCES;
>
> + }
>
> +
>
> + UnicodeStrToAsciiStrS (Host, RequestHeader.FieldValue, StringSize);
>
> +
>
> + RequestMessage.HeaderCount++;
>
> +
>
> + RequestData.Method = HttpMethodGet;
>
> + RequestData.Url = DownloadUrl;
>
> +
>
> + RequestMessage.Data.Request = &RequestData;
>
> + RequestMessage.Headers = &RequestHeader;
>
> + RequestMessage.BodyLength = 0;
>
> + RequestMessage.Body = NULL;
>
> + Context->RequestToken.Event = NULL;
>
> +
>
> + //
>
> + // Completion callback event to be set when Request completes.
>
> + //
>
> + Status = gBS->CreateEvent (
>
> + EVT_NOTIFY_SIGNAL,
>
> + TPL_CALLBACK,
>
> + RequestCallback,
>
> + Context,
>
> + &Context->RequestToken.Event
>
> + );
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + Context->RequestToken.Status = EFI_SUCCESS;
>
> + Context->RequestToken.Message = &RequestMessage;
>
> + gRequestCallbackComplete = FALSE;
>
> + Status = Context->Http->Request (Context->Http,
&Context->RequestToken);
>
> + if (EFI_ERROR (Status)) {
>
> + goto Error;
>
> + }
>
> +
>
> + Status = WaitForCompletion (Context, &gRequestCallbackComplete);
>
> + if (EFI_ERROR (Status)) {
>
> + Context->Http->Cancel (Context->Http, &Context->RequestToken);
>
> + }
>
> +Error:
>
> + SHELL_FREE_NON_NULL (RequestHeader.FieldValue);
>
> + if (Context->RequestToken.Event) {
>
> + gBS->CloseEvent (Context->RequestToken.Event);
>
> + ZeroMem (&Context->RequestToken, sizeof (Context->RequestToken));
>
> + }
>
> +
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Update the progress of a file download
>
> + This procedure is called each time a new HTTP body portion is
received.
>
> +
>
> + @param[in] Context HTTP download context.
>
> + @param[in] DownloadLen Portion size, in bytes.
>
> + @param[in] Buffer The pointer to the parsed buffer.
>
> +
>
> + @retval EFI_SUCCESS Portion saved.
>
> + @retval Other Error saving the portion.
>
> +
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +EFIAPI
>
> +SavePortion (
>
> + IN DOWNLOAD_CONTEXT *Context,
>
> + IN UINTN DownloadLen,
>
> + IN CHAR8 *Buffer
>
> + )
>
> +{
>
> + CHAR16 Progress[HTTP_PROGRESS_MESSAGE_SIZE];
>
> + UINTN NbOfKb;
>
> + UINTN Index;
>
> + UINTN LastStep;
>
> + UINTN Step;
>
> + EFI_STATUS Status;
>
> +
>
> + LastStep = 0;
>
> + Step = 0;
>
> + ShellSetFilePosition (mFileHandle, Context->LastReportedNbOfBytes);
>
> + Status = ShellWriteFile (mFileHandle, &DownloadLen, Buffer);
>
> + if (EFI_ERROR (Status)) {
>
> + if (Context->ContentDownloaded > 0) {
>
> + ShellPrintHiiEx (
>
> + -1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF), mHttpHiiHandle
>
> + );
>
> + }
>
> +
>
> + ShellPrintHiiEx (
>
> + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_WRITE),
>
> + mHttpHiiHandle, mLocalFilePath, Status
>
> + );
>
> +
>
> + return Status;
>
> + }
>
> +
>
> + if (Context->ContentDownloaded == 0) {
>
> + ShellPrintEx (-1, -1, L"%s 0 Kb", HTTP_PROGR_FRAME);
>
> + }
>
> +
>
> + Context->ContentDownloaded += DownloadLen;
>
> + NbOfKb = Context->ContentDownloaded >> 10;
>
> +
>
> + Progress[0] = L'\0';
>
> + if (Context->ContentLength) {
>
> + LastStep = (Context->LastReportedNbOfBytes *
> HTTP_PROGRESS_SLIDER_STEPS) /
>
> + Context->ContentLength;
>
> + Step = (Context->ContentDownloaded *
HTTP_PROGRESS_SLIDER_STEPS) /
>
> + Context->ContentLength;
>
> + }
>
> +
>
> + Context->LastReportedNbOfBytes = Context->ContentDownloaded;
>
> +
>
> + if (Step <= LastStep) {
>
> + if (!Context->ContentLength) {
>
> + //
>
> + // Update downloaded size, there is no length info available.
>
> + //
>
> + ShellPrintEx (-1, -1, L"%s", HTTP_KB);
>
> + ShellPrintEx (-1, -1, L"%7d Kb", NbOfKb);
>
> + }
>
> +
>
> + return EFI_SUCCESS;
>
> + }
>
> +
>
> + ShellPrintEx (-1, -1, L"%s", HTTP_PROGRESS_DEL);
>
> +
>
> + Status = StrCpyS (Progress, HTTP_PROGRESS_MESSAGE_SIZE,
> HTTP_PROGR_FRAME);
>
> + if (EFI_ERROR (Status)) {
>
> + return Status;
>
> + }
>
> +
>
> + for (Index = 1; Index < Step; Index++) {
>
> + Progress[Index] = L'=';
>
> + }
>
> +
>
> + if (Step) {
>
> + Progress[Step] = L'>';
>
> + }
>
> +
>
> + UnicodeSPrint (
>
> + Progress + (sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) - 1,
>
> + sizeof (Progress) - sizeof (HTTP_PROGR_FRAME),
>
> + L" %7d Kb",
>
> + NbOfKb
>
> + );
>
> +
>
> +
>
> + ShellPrintEx (-1, -1, L"%s", Progress);
>
> +
>
> + return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> + Replace the original Host and URI with Host and URI returned by the
>
> + HTTP server in 'Location' header (redirection).
>
> +
>
> + @param[in] Location A pointer to the 'Location' string
>
> + provided by HTTP server.
>
> + @param[in] Context A pointer to HTTP download context.
>
> + @param[in] DownloadUrl Fully qualified HTTP URL.
>
> +
>
> + @return EFI_SUCCESS Host and URI were successfully set.
>
> + @return EFI_OUT_OF_RESOURCES Error setting Host or URI.
>
> +**/
>
> +
>
> +STATIC
>
> +EFI_STATUS
>
> +SetHostURI (
>
> + IN CHAR8 *Location,
>
> + IN DOWNLOAD_CONTEXT *Context,
>
> + IN CHAR16 *DownloadUrl
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN StringSize;
>
> + UINTN FirstStep;
>
> + CHAR8 *Tmp;
>
> + CHAR16 *Url;
>
> + BOOLEAN IsAbEmptyUrl;
>
> +
>
> + Tmp = NULL;
>
> + Url = NULL;
>
> + IsAbEmptyUrl = FALSE;
>
> + FirstStep = 0;
>
> +
>
> + StringSize = (AsciiStrSize (Location) * sizeof (CHAR16));
>
> + Url = AllocateZeroPool (StringSize);
>
> + if (!Url) {
>
> + return EFI_OUT_OF_RESOURCES;
>
> + }
>
> +
>
> + Status = AsciiStrToUnicodeStrS (
>
> + (CONST CHAR8 *)Location,
>
> + Url,
>
> + StringSize
>
> + );
>
> +
>
> + if (EFI_ERROR (Status)) {
>
> + goto Error;
>
> + }
>
> +
>
> + //
>
> + // If an HTTP server redirect to the same location more than once,
>
> + // then stop attempts and tell it is not reachable.
>
> + //
>
> + if (!StrCmp (Url, DownloadUrl)) {
>
> + Status = EFI_NO_MAPPING;
>
> + goto Error;
>
> + }
>
> +
>
> + if (AsciiStrLen (Location) > 2) {
>
> + // Some servers return 'Location: //server/resource'
>
> + IsAbEmptyUrl = (Location[0] == '/') && (Location[1] == '/');
>
> + if (IsAbEmptyUrl) {
>
> + // Skip first "//"
>
> + Location += 2;
>
> + FirstStep = 1;
>
> + }
>
> + }
>
> +
>
> + if (AsciiStrStr (Location, "://") || IsAbEmptyUrl) {
>
> + CHAR8 *Walker;
>
> + CHAR16 *Temp;
>
> + UINTN Idx;
>
> + UINTN Step;
>
> +
>
> + Idx = 0;
>
> + Walker = Location;
>
> +
>
> + for (Step = FirstStep; Step < 2; Step++) {
>
> + for (; *Walker != '/' && *Walker != '\0'; Walker++) {
>
> + Idx++;
>
> + }
>
> + if (!Step) {
>
> + //
>
> + // Skip "//"
>
> + //
>
> + Idx += 2;
>
> + Walker += 2;
>
> + }
>
> + }
>
> +
>
> + Tmp = AllocateZeroPool (Idx + 1);
>
> + if (!Tmp) {
>
> + Status = EFI_OUT_OF_RESOURCES;
>
> + goto Error;
>
> + }
>
> +
>
> + CopyMem (Tmp, Location, Idx);
>
> +
>
> + //
>
> + // Location now points to URI
>
> + //
>
> + Location += Idx;
>
> + StringSize = (Idx + 1) * sizeof (CHAR16);
>
> +
>
> + SHELL_FREE_NON_NULL (Context->ServerAddrAndProto);
>
> +
>
> + Temp = AllocateZeroPool (StringSize);
>
> + if (!Temp) {
>
> + Status = EFI_OUT_OF_RESOURCES;
>
> + goto Error;
>
> + }
>
> +
>
> + Status = AsciiStrToUnicodeStrS (
>
> + (CONST CHAR8 *)Tmp,
>
> + Temp,
>
> + StringSize
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + SHELL_FREE_NON_NULL (Temp);
>
> + goto Error;
>
> + }
>
> +
>
> + Idx = 0;
>
> + if (IsAbEmptyUrl) {
>
> + Context->ServerAddrAndProto = StrnCatGrow (
>
> + &Context->ServerAddrAndProto,
>
> + &Idx,
>
> + L"http://",
>
> + StrLen (L"http://")
>
> + );
>
> + }
>
> +
>
> + Context->ServerAddrAndProto = StrnCatGrow (
>
> + &Context->ServerAddrAndProto,
>
> + &Idx,
>
> + Temp,
>
> + StrLen (Temp)
>
> + );
>
> + SHELL_FREE_NON_NULL (Temp);
>
> + if (!Context->ServerAddrAndProto) {
>
> + Status = EFI_OUT_OF_RESOURCES;
>
> + goto Error;
>
> + }
>
> + }
>
> +
>
> + SHELL_FREE_NON_NULL (Context->URI);
>
> +
>
> + StringSize = AsciiStrSize (Location) * sizeof (CHAR16);
>
> + Context->URI = AllocateZeroPool (StringSize);
>
> + if (!Context->URI) {
>
> + Status = EFI_OUT_OF_RESOURCES;
>
> + goto Error;
>
> + }
>
> +
>
> + //
>
> + // Now make changes to the URI part.
>
> + //
>
> + Status = AsciiStrToUnicodeStrS (
>
> + (CONST CHAR8 *)Location,
>
> + Context->URI,
>
> + StringSize
>
> + );
>
> +Error:
>
> + SHELL_FREE_NON_NULL (Tmp);
>
> + SHELL_FREE_NON_NULL (Url);
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Message parser callback.
>
> + Save a portion of HTTP body.
>
> +
>
> + @param[in] EventType Type of event. Can be either
>
> + OnComplete or OnData.
>
> + @param[in] Data A pointer to the buffer with data.
>
> + @param[in] Length Data length of this portion.
>
> + @param[in] Context A pointer to the HTTP download context.
>
> +
>
> + @return EFI_SUCCESS The portion was processed successfully.
>
> + @return Other Error returned by SavePortion.
>
> +**/
>
> +
>
> +STATIC
>
> +EFI_STATUS
>
> +EFIAPI
>
> +ParseMsg (
>
> + IN HTTP_BODY_PARSE_EVENT EventType,
>
> + IN CHAR8 *Data,
>
> + IN UINTN Length,
>
> + IN VOID *Context
>
> + )
>
> +{
>
> + if (!Data || (EventType == BodyParseEventOnComplete) || !Context) {
>
> + return EFI_SUCCESS;
>
> + }
>
> +
>
> + return SavePortion (Context, Length, Data);
>
> +}
>
> +
>
> +
>
> +/**
>
> + Get HTTP server response and collect the whole body as a file.
>
> + Set appropriate status in Context (REQ_OK, REQ_REPEAT, REQ_ERROR).
>
> + Note that even if HTTP server returns an error code, it might send
>
> + the body as well. This body will be collected in the resultant file.
>
> +
>
> + @param[in] Context A pointer to the HTTP download context.
>
> + @param[in] DownloadedUrl A pointer to the fully qualified URL to
download.
>
> +
>
> + @return EFI_SUCCESS Valid file. Body successfully collected.
>
> + @return EFI_HTTP_ERROR Response is a valid HTTP response, but
the
>
> + HTTP server
>
> + indicated an error (HTTP code >= 400).
>
> + Response body MAY contain full
>
> + HTTP server response.
>
> + @return Others Error getting the reponse from the HTTP
server.
>
> + Response body is not collected.
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +GetResponse (
>
> + IN DOWNLOAD_CONTEXT *Context,
>
> + IN CHAR16 *DownloadUrl
>
> + )
>
> +{
>
> + EFI_HTTP_RESPONSE_DATA ResponseData;
>
> + EFI_HTTP_MESSAGE ResponseMessage;
>
> + EFI_STATUS Status;
>
> + VOID *MsgParser;
>
> + BOOLEAN IsTrunked;
>
> +
>
> + ZeroMem (&ResponseData, sizeof (ResponseData));
>
> + ZeroMem (&ResponseMessage, sizeof (ResponseMessage));
>
> + ZeroMem (&Context->ResponseToken, sizeof (Context->ResponseToken));
>
> + IsTrunked = FALSE;
>
> +
>
> + ResponseMessage.Body = Context->Buffer;
>
> + Context->ResponseToken.Status = EFI_SUCCESS;
>
> + Context->ResponseToken.Message = &ResponseMessage;
>
> + Context->ContentLength = 0;
>
> + Context->Status = REQ_OK;
>
> + MsgParser = NULL;
>
> + ResponseData.StatusCode = HTTP_STATUS_UNSUPPORTED_STATUS;
>
> + ResponseMessage.Data.Response = &ResponseData;
>
> + Context->ResponseToken.Event = NULL;
>
> +
>
> + do {
>
> + SHELL_FREE_NON_NULL (ResponseMessage.Headers);
>
> + ResponseMessage.HeaderCount = 0;
>
> + gResponseCallbackComplete = FALSE;
>
> + ResponseMessage.BodyLength = Context->BufferSize;
>
> +
>
> + if (ShellGetExecutionBreakFlag ()) {
>
> + Status = EFI_ABORTED;
>
> + break;
>
> + }
>
> +
>
> + if (!Context->ContentDownloaded && !Context->ResponseToken.Event)
{
>
> + Status = gBS->CreateEvent (
>
> + EVT_NOTIFY_SIGNAL,
>
> + TPL_CALLBACK,
>
> + ResponseCallback,
>
> + Context,
>
> + &Context->ResponseToken.Event
>
> + );
>
> + ASSERT_EFI_ERROR (Status);
>
> + } else {
>
> + ResponseMessage.Data.Response = NULL;
>
> + }
>
> +
>
> + if (EFI_ERROR (Status)) {
>
> + break;
>
> + }
>
> +
>
> + Status = Context->Http->Response (Context->Http, &Context-
> >ResponseToken);
>
> + if (EFI_ERROR (Status)) {
>
> + break;
>
> + }
>
> +
>
> + Status = WaitForCompletion (Context, &gResponseCallbackComplete);
>
> + if (EFI_ERROR (Status) && ResponseMessage.HeaderCount) {
>
> + Status = EFI_SUCCESS;
>
> + }
>
> +
>
> + if (EFI_ERROR (Status)) {
>
> + Context->Http->Cancel (Context->Http, &Context->ResponseToken);
>
> + break;
>
> + }
>
> +
>
> + if (!Context->ContentDownloaded) {
>
> + EFI_HTTP_HEADER *Header;
>
> + BOOLEAN Redirection;
>
> +
>
> + Redirection =
>
> + ((ResponseData.StatusCode >=
HTTP_STATUS_300_MULTIPLE_CHOICES)
> &&
>
> + (ResponseData.StatusCode <=
> HTTP_STATUS_307_TEMPORARY_REDIRECT)
>
> + ) ||
>
> + (ResponseData.StatusCode ==
> HTTP_STATUS_308_PERMANENT_REDIRECT);
>
> +
>
> + if (Redirection) {
>
> + //
>
> + // Need to repeat the request with new Location (server
redirected).
>
> + //
>
> + Context->Status = REQ_NEED_REPEAT;
>
> +
>
> + Header = HttpFindHeader (
>
> + ResponseMessage.HeaderCount,
>
> + ResponseMessage.Headers,
>
> + "Location"
>
> + );
>
> + if (Header) {
>
> + Status = SetHostURI (Header->FieldValue, Context,
DownloadUrl);
>
> + if (Status == EFI_NO_MAPPING) {
>
> + ShellPrintHiiEx (
>
> + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_STATUSCODE),
>
> + mHttpHiiHandle, Context->ServerAddrAndProto,
>
> + L"Recursive HTTP server relocation",
>
> + Context->URI
>
> + );
>
> + }
>
> + } else {
>
> + //
>
> + // Bad reply from the server. Server must specify the
location.
>
> + // Indicate that resource was not found, and no body
collected.
>
> + //
>
> + Status = EFI_NOT_FOUND;
>
> + }
>
> +
>
> + Context->Http->Cancel (Context->Http,
&Context->ResponseToken);
>
> +
>
> + break;
>
> + }
>
> +
>
> + //
>
> + // Init message-body parser by header information.
>
> + //
>
> + if (!MsgParser) {
>
> + Status = HttpInitMsgParser (
>
> + ResponseMessage.Data.Request->Method,
>
> + ResponseData.StatusCode,
>
> + ResponseMessage.HeaderCount,
>
> + ResponseMessage.Headers,
>
> + ParseMsg,
>
> + Context,
>
> + &MsgParser
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + break;
>
> + }
>
> + }
>
> +
>
> + //
>
> + // If it is a trunked message, rely on the parser.
>
> + //
>
> + Header = HttpFindHeader (
>
> + ResponseMessage.HeaderCount,
>
> + ResponseMessage.Headers,
>
> + "Transfer-Encoding"
>
> + );
>
> + IsTrunked = (Header && !AsciiStrCmp (Header->FieldValue,
"chunked"));
>
> +
>
> + HttpGetEntityLength (MsgParser, &Context->ContentLength);
>
> +
>
> + if (ResponseData.StatusCode >= HTTP_STATUS_400_BAD_REQUEST &&
>
> + (ResponseData.StatusCode !=
> HTTP_STATUS_308_PERMANENT_REDIRECT)
>
> + ) {
>
> + //
>
> + // Server reported an error via Response code.
>
> + // Collect the body if any.
>
> + //
>
> + if (!gHttpError) {
>
> + CONST CHAR16 *Desc;
>
> +
>
> + gHttpError = TRUE;
>
> +
>
> + Desc = ErrStatusDesc[ResponseData.StatusCode -
>
> + HTTP_STATUS_400_BAD_REQUEST];
>
> + ShellPrintHiiEx (
>
> + -1, -1, NULL, STRING_TOKEN
(STR_HTTP_ERR_STATUSCODE),
>
> + mHttpHiiHandle, Context->ServerAddrAndProto,
>
> + Desc,
>
> + Context->URI
>
> + );
>
> +
>
> + //
>
> + // This gives an RFC HTTP error.
>
> + //
>
> + Context->Status = ShellStrToUintn (Desc);
>
> + }
>
> + }
>
> + }
>
> +
>
> + // Do NOT try to parse an empty body.
>
> + if (ResponseMessage.BodyLength || IsTrunked) {
>
> + Status = HttpParseMessageBody (
>
> + MsgParser,
>
> + ResponseMessage.BodyLength,
>
> + ResponseMessage.Body
>
> + );
>
> + }
>
> + } while (!HttpIsMessageComplete (MsgParser) &&
>
> + !EFI_ERROR (Status) &&
>
> + ResponseMessage.BodyLength
>
> + );
>
> +
>
> + SHELL_FREE_NON_NULL (MsgParser);
>
> + if (Context->ResponseToken.Event) {
>
> + gBS->CloseEvent (Context->ResponseToken.Event);
>
> + ZeroMem (&Context->ResponseToken, sizeof
(Context->ResponseToken));
>
> + }
>
> +
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Worker function that downloads the data of a file from an HTTP server
given
>
> + the path of the file and its size.
>
> +
>
> + @param[in] Context A pointer to the HTTP download
context.
>
> +
>
> + @retval EFI_SUCCESS The file was downloaded.
>
> + @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
>
> + #retval EFI_HTTP_ERROR The server returned a valid HTTP
error.
>
> + Examine the mLocalFilePath file
>
> + to get error body.
>
> + @retval Others The downloading of the file from the
server
>
> + failed.
>
> +
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +DownloadFile (
>
> + IN DOWNLOAD_CONTEXT *Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + CHAR16 *DownloadUrl;
>
> + UINTN UrlSize;
>
> +
>
> + ASSERT (Context);
>
> +
>
> + DownloadUrl = NULL;
>
> +
>
> + Context->Buffer = AllocatePool (Context->BufferSize);
>
> + if (!Context->Buffer) {
>
> + Status = EFI_OUT_OF_RESOURCES;
>
> + goto ON_EXIT;
>
> + }
>
> +
>
> + //
>
> + // OPEN FILE
>
> + //
>
> + if (!EFI_ERROR (ShellFileExists (mLocalFilePath))) {
>
> + ShellDeleteFileByName (mLocalFilePath);
>
> + }
>
> +
>
> + Status = ShellOpenFileByName (
>
> + mLocalFilePath,
>
> + &mFileHandle,
>
> + EFI_FILE_MODE_CREATE |
>
> + EFI_FILE_MODE_WRITE |
>
> + EFI_FILE_MODE_READ,
>
> + 0);
>
> + if (EFI_ERROR (Status)) {
>
> + ShellPrintHiiEx (
>
> + -1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL),
>
> + mHttpHiiHandle, HTTP_APP_NAME, mLocalFilePath
>
> + );
>
> + goto ON_EXIT;
>
> + }
>
> +
>
> + do {
>
> + SHELL_FREE_NON_NULL (DownloadUrl);
>
> + UrlSize = 0;
>
> + DownloadUrl = StrnCatGrow (
>
> + &DownloadUrl,
>
> + &UrlSize,
>
> + Context->ServerAddrAndProto,
>
> + StrLen (Context->ServerAddrAndProto)
>
> + );
>
> + if (Context->URI[0] != L'/') {
>
> + DownloadUrl = StrnCatGrow (
>
> + &DownloadUrl,
>
> + &UrlSize,
>
> + L"/",
>
> + StrLen (Context->ServerAddrAndProto)
>
> + );
>
> + }
>
> +
>
> + DownloadUrl = StrnCatGrow (
>
> + &DownloadUrl,
>
> + &UrlSize,
>
> + Context->URI,
>
> + StrLen (Context->URI));
>
> +
>
> + ShellPrintHiiEx (
>
> + -1, -1, NULL, STRING_TOKEN (STR_HTTP_DOWNLOADING),
>
> + mHttpHiiHandle, DownloadUrl);
>
> +
>
> + Status = SendRequest (Context, DownloadUrl);
>
> + if (Status) {
>
> + goto ON_EXIT;
>
> + }
>
> +
>
> + Status = GetResponse (Context, DownloadUrl);
>
> +
>
> + if (Status) {
>
> + goto ON_EXIT;
>
> + }
>
> +
>
> + } while (Context->Status == REQ_NEED_REPEAT);
>
> +
>
> + if (Context->Status) {
>
> + Status = ENCODE_ERROR (Context->Status);
>
> + }
>
> +
>
> +ON_EXIT:
>
> + //
>
> + // CLOSE FILE
>
> + //
>
> + if (mFileHandle) {
>
> + ShellCloseFile (&mFileHandle);
>
> + }
>
> +
>
> + SHELL_FREE_NON_NULL (DownloadUrl);
>
> + SHELL_FREE_NON_NULL (Context->Buffer);
>
> +
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Retrive HII package list from ImageHandle and publish to HII
database.
>
> +
>
> + @param ImageHandle The image handle of the process.
>
> +
>
> + @return HII handle.
>
> +**/
>
> +EFI_HII_HANDLE
>
> +InitializeHiiPackage (
>
> + EFI_HANDLE ImageHandle
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + EFI_HII_PACKAGE_LIST_HEADER *PackageList;
>
> + EFI_HII_HANDLE HiiHandle;
>
> +
>
> + //
>
> + // Retrieve HII package list from ImageHandle
>
> + //
>
> + Status = gBS->OpenProtocol (
>
> + ImageHandle,
>
> + &gEfiHiiPackageListProtocolGuid,
>
> + (VOID **)&PackageList,
>
> + ImageHandle,
>
> + NULL,
>
> + EFI_OPEN_PROTOCOL_GET_PROTOCOL
>
> + );
>
> + ASSERT_EFI_ERROR (Status);
>
> + if (EFI_ERROR (Status)) {
>
> + return NULL;
>
> + }
>
> +
>
> + //
>
> + // Publish HII package list to HII Database.
>
> + //
>
> + Status = gHiiDatabase->NewPackageList (
>
> + gHiiDatabase,
>
> + PackageList,
>
> + NULL,
>
> + &HiiHandle
>
> + );
>
> + ASSERT_EFI_ERROR (Status);
>
> + if (EFI_ERROR (Status)) {
>
> + return NULL;
>
> + }
>
> + return HiiHandle;
>
> +}
>
> diff --git a/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h
> b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h
> new file mode 100644
> index 000000000000..a142b96f6ad2
> --- /dev/null
> +++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h
> @@ -0,0 +1,84 @@
> +/** @file
>
> + Header file for 'http' command functions.
>
> +
>
> + Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
<BR>
>
> + Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
>
> + Copyright (c) 2020, Broadcom. All rights reserved.<BR>
>
> +
>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#ifndef _HTTP_H_
>
> +#define _HTTP_H_
>
> +
>
> +#include <Uefi.h>
>
> +
>
> +#include <Library/BaseLib.h>
>
> +#include <Library/BaseMemoryLib.h>
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/HiiLib.h>
>
> +#include <Library/HttpLib.h>
>
> +#include <Library/MemoryAllocationLib.h>
>
> +#include <Library/NetLib.h>
>
> +#include <Library/PrintLib.h>
>
> +#include <Library/ShellLib.h>
>
> +#include <Library/UefiBootServicesTableLib.h>
>
> +#include <Library/UefiHiiServicesLib.h>
>
> +#include <Library/UefiLib.h>
>
> +#include <Library/UefiRuntimeServicesTableLib.h>
>
> +
>
> +#include <Protocol/HiiPackageList.h>
>
> +#include <Protocol/HttpUtilities.h>
>
> +#include <Protocol/ServiceBinding.h>
>
> +
>
> +#define HTTP_APP_NAME L"http"
>
> +
>
> +#define REQ_OK 0
>
> +#define REQ_NEED_REPEAT 1
>
> +
>
> +extern EFI_HII_HANDLE mHttpHiiHandle;
>
> +
>
> +typedef struct {
>
> + UINTN ContentDownloaded;
>
> + UINTN ContentLength;
>
> + UINTN LastReportedNbOfBytes;
>
> + UINTN BufferSize;
>
> + UINTN Status;
>
> + UINT8 *Buffer;
>
> + CHAR16 *ServerAddrAndProto;
>
> + CHAR16 *URI;
>
> + EFI_HTTP_TOKEN ResponseToken;
>
> + EFI_HTTP_TOKEN RequestToken;
>
> + EFI_HTTP_PROTOCOL *Http;
>
> +} DOWNLOAD_CONTEXT;
>
> +
>
> +/**
>
> + Function for 'http' command.
>
> +
>
> + @param[in] ImageHandle The image handle.
>
> + @param[in] SystemTable The system table.
>
> +
>
> + @retval SHELL_SUCCESS Command completed successfully.
>
> + @retval SHELL_INVALID_PARAMETER Command usage error.
>
> + @retval SHELL_ABORTED The user aborts the operation.
>
> + @retval value Unknown error.
>
> +**/
>
> +SHELL_STATUS
>
> +RunHttp (
>
> + IN EFI_HANDLE ImageHandle,
>
> + IN EFI_SYSTEM_TABLE *SystemTable
>
> + );
>
> +
>
> +/**
>
> + Retrive HII package list from ImageHandle and publish to HII
database.
>
> +
>
> + @param ImageHandle The image handle of the process.
>
> +
>
> + @return HII handle.
>
> +**/
>
> +EFI_HII_HANDLE
>
> +InitializeHiiPackage (
>
> + EFI_HANDLE ImageHandle
>
> + );
>
> +#endif // _HTTP_H_
>
> diff --git a/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni
> b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni
> new file mode 100644
> index 000000000000..efe50e25819c
> --- /dev/null
> +++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni
> @@ -0,0 +1,113 @@
> +// /**
>
> +//
>
> +// (C) Copyright 2015-2016 Hewlett Packard Enterprise Development
LP<BR>
>
> +// Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
<BR>
>
> +// Copyright (c) 2020, Broadcom. All rights reserved.<BR>
>
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +//
>
> +// Module Name:
>
> +//
>
> +// Http.uni
>
> +//
>
> +// Abstract:
>
> +//
>
> +// String definitions for UEFI Shell HTTP command
>
> +//
>
> +//
>
> +// **/
>
> +
>
> +/=#
>
> +
>
> +#langdef en-US "english"
>
> +
>
> +#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too many
> arguments. Try help http.\r\n"
>
> +#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few
> arguments. Try help http.\r\n"
>
> +#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid
> argument - '%H%s%N'. Try help http.\r\n"
>
> +#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown
flag -
> '%H%s%N'. Try help http.\r\n"
>
> +#string STR_GEN_FILE_OPEN_FAIL #language en-US "%H%s%N: Cannot open
> file - '%H%s%N'\r\n"
>
> +#string STR_GEN_CRLF #language en-US "\r\n"
>
> +
>
> +#string STR_HTTP_ERR_NO_NIC #language en-US "No network
interface
> card found.\r\n"
>
> +#string STR_HTTP_ERR_NIC_NAME #language en-US "Failed to get the
name
> of the network interface card number %d - %r\r\n"
>
> +#string STR_HTTP_ERR_OPEN_PROTOCOL #language en-US "Unable to open
> HTTP protocol on '%H%s%N' - %r\r\n"
>
> +#string STR_HTTP_ERR_CONFIGURE #language en-US "Unable to configure
> HTTP protocol on '%H%s%N' - %r\r\n"
>
> +#string STR_HTTP_ERR_DOWNLOAD #language en-US "Unable to download
> the file '%H%s%N' on '%H%s%N' - %r\r\n"
>
> +#string STR_HTTP_ERR_WRITE #language en-US "Unable to write
into file
> '%H%s%N' - %r\r\n"
>
> +#string STR_HTTP_ERR_NIC_NOT_FOUND #language en-US "Network Interface
> Card '%H%s%N' not found.\r\n"
>
> +#string STR_HTTP_ERR_STATUSCODE #language en-US "\r'%H%s%N' reports
> '%s' for '%H%s%N' \r\n"
>
> +#string STR_HTTP_DOWNLOADING #language en-US "Downloading
> '%H%s%N'\r\n"
>
> +
>
> +#string STR_GET_HELP_HTTP #language en-US ""
>
> +".TH http 0 "Download a file from HTTP server."\r\n"
>
> +".SH NAME\r\n"
>
> +"Download a file from HTTP server.\r\n"
>
> +".SH SYNOPSIS\r\n"
>
> +" \r\n"
>
> +"HTTP [-i interface] [-l port] [-t timeout] [-s size]\r\n"
>
> +" <URL> [localfilepath]\r\n"
>
> +".SH OPTIONS\r\n"
>
> +" \r\n"
>
> +" -i interface - Specifies an adapter name, i.e., eth0.\r\n"
>
> +" -l port - Specifies the local port number. Default value is
0\r\n"
>
> +" and the port number is automatically
assigned.\r\n"
>
> +" -s size The size of the download buffer for a chunk, in
bytes.\r\n"
>
> +" Default is 32K. Note that larger buffer does not
imply\r\n"
>
> +" better speed.\r\n"
>
> +" -t timeout - The number of seconds to wait for completion
of\r\n"
>
> +" requests and responses. Default is 0 which is
'automatic'.\r\n"
>
> +" %HURL%N\r\n"
>
> +" Two types of providing of URLs are supported:\r\n"
>
> +" 1. tftp like, where host and http_uri are separate parameters\r\n"
>
> +" (example: host /host_uri), and\r\n\"
>
> +" 2. wget-like, where host and host_uri is one parameter.\r\n"
>
> +" (example: host/host_uri)\r\n"
>
> +"\r\n"
>
> +" host - Specifies HTTP Server address.\r\n
>
> + Can be either IPv4 address or 'http (or
https)://addr'\r\n
>
> + Can use addresses resolvable by DNS as well.
\r\n
>
> + Port can be specified after ':' if needed. \r\n
>
> + By default port 80 is used.\r\n"
>
> +" http_uri - HTTP server URI to download the file.\r\n"
>
> +"\r\n"
>
> +" localfilepath - Local destination file path.\r\n"
>
> +".SH DESCRIPTION\r\n"
>
> +" \r\n"
>
> +"NOTES:\r\n"
>
> +" 1. The HTTP command allows geting of the file specified by its
'http_uri'\r\n"
>
> +" path from the HTTP server specified by its 'host' IPv4 address.
If the\r\n"
>
> +" optional 'localfilepath' parameter is provided, the downloaded
file is\r\n"
>
> +" stored locally using the provided file path. If the local file
path is\r\n"
>
> +" not specified, the file is stored in the current directory using
the file\r\n"
>
> +" server's name.\r\n"
>
> +" 2. Before using the HTTP command, the network interface intended to
> be\r\n"
>
> +" used to retrieve the file must be configured. This configuration
may be\r\n"
>
> +" done by means of the 'ifconfig' command.\r\n"
>
> +" 3. If a network interface is defined with the '-i' option then only
this\r\n"
>
> +" interface will be used to retrieve the remote file. Otherwise,
all
> network\r\n"
>
> +" interfaces are tried in the order they have been discovered
during the\r\n"
>
> +" DXE phase.\r\n"
>
> +".SH EXAMPLES\r\n"
>
> +" \r\n"
>
> +"EXAMPLES:\r\n"
>
> +" * To get the file "dir1/file1.dat" from the HTTP server 192.168.1.1,
port 8080,
> and\r\n"
>
> +" store it as file2.dat in the current directory :\r\n"
>
> +" fs0:\> http 192.168.1.1:8080 dir1/file1.dat file2.dat\r\n"
>
> +" * To get the file /image.bin via HTTPS from server 192.168.1.1 at
port 443
> \r\n"
>
> +" (default HTTPS port), and store it in the current directory: \r\n"
>
> +" fs0:\> http https://192.168.1.1 image.bin\r\n"
>
> +" To get an index file from http://google.com and place it into the
\r\n"
>
> +" current directory:\r\n"
>
> +" fs0:\> http google.com index.html"
>
> +".SH RETURNVALUES\r\n"
>
> +" \r\n"
>
> +"RETURN VALUES:\r\n"
>
> +" SHELL_SUCCESS The action was completed as
requested.\r\n"
>
> +" SHELL_INVALID_PARAMETER One of the passed-in parameters was
> incorrectly\r\n"
>
> +" formatted or its value was out of
bounds.\r\n"
>
> +" SHELL_HTTP_ERROR No EFI errors, but the server reported a
status
> code\r\n
>
> + which should be treated as an error. If an
error body sent\r\n
>
> + by the server, it would be saved either
as\r\n
>
> + localfilepath filename, or as an URI name
in the current
> directory.\r\n
>
> + If '/' is at the end of the URL, and no
locafilepath filename\r\n
>
> + is given on the command line, the file
will be retrieved as\r\n
>
> + index.html."
>
> diff --git a/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c
> b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c
> new file mode 100644
> index 000000000000..7bd5b46d3997
> --- /dev/null
> +++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c
> @@ -0,0 +1,53 @@
> +/** @file
>
> + Entrypoint of "http" shell standalone application.
>
> +
>
> + Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
<BR>
>
> + Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
>
> + Copyright (c) 2020, Broadcom. All rights reserved.<BR>
>
> +
>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +#include "Http.h"
>
> +
>
> +/*
>
> + * String token ID of help message text.
>
> + * Shell supports to find help message in the resource section of an
>
> + * application image if * .MAN file is not found.
>
> + * This global variable is added to make build tool recognizes
>
> + * that the help string is consumed by user and then build tool will
>
> + * add the string into the resource section.
>
> + * Thus the application can use '-?' option to show help message in
Shell.
>
> + */
>
> +GLOBAL_REMOVE_IF_UNREFERENCED
>
> +EFI_STRING_ID mStringHelpTokenId = STRING_TOKEN (STR_GET_HELP_HTTP);
>
> +
>
> +/**
>
> + Entry point of Http standalone application.
>
> +
>
> + @param ImageHandle The image handle of the process.
>
> + @param SystemTable The EFI System Table pointer.
>
> +
>
> + @retval EFI_SUCCESS Http command is executed sucessfully.
>
> + @retval EFI_ABORTED HII package was failed to initialize.
>
> + @retval others Other errors when executing http
command.
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +HttpAppInitialize (
>
> + IN EFI_HANDLE ImageHandle,
>
> + IN EFI_SYSTEM_TABLE *SystemTable
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + mHttpHiiHandle = InitializeHiiPackage (ImageHandle);
>
> + if (mHttpHiiHandle == NULL) {
>
> + return EFI_ABORTED;
>
> + }
>
> +
>
> + Status = (EFI_STATUS)RunHttp (ImageHandle, SystemTable);
>
> +
>
> + HiiRemovePackages (mHttpHiiHandle);
>
> +
>
> + return Status;
>
> +}
>
> diff --git a/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
> b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
> new file mode 100644
> index 000000000000..d08d47fb37d5
> --- /dev/null
> +++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
> @@ -0,0 +1,58 @@
> +## @file
>
> +# Provides Shell 'http' standalone application.
>
> +#
>
> +# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.
<BR>
>
> +# Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
>
> +# Copyright (c) 2020, Broadcom. All rights reserved.<BR>
>
> +#
>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +#
>
> +#
>
> +##
>
> +
>
> +[Defines]
>
> + INF_VERSION = 0x00010006
>
> + BASE_NAME = http
>
> + FILE_GUID = 56B00FB7-91D2-869B-CE5C-26CD1A89C73C
>
> + MODULE_TYPE = UEFI_APPLICATION
>
> + VERSION_STRING = 1.0
>
> + ENTRY_POINT = HttpAppInitialize
>
> +#
>
> +# This flag specifies whether HII resource section is generated into
PE image.
>
> +#
>
> + UEFI_HII_RESOURCE_SECTION = TRUE
>
> +
>
> +[Sources.common]
>
> + Http.c
>
> + HttpApp.c
>
> + Http.h
>
> + Http.uni
>
> +
>
> +[Packages]
>
> + EmbeddedPkg/EmbeddedPkg.dec
>
> + MdeModulePkg/MdeModulePkg.dec
>
> + MdePkg/MdePkg.dec
>
> + NetworkPkg/NetworkPkg.dec
>
> + ShellPkg/ShellPkg.dec
>
> +
>
> +[LibraryClasses]
>
> + BaseLib
>
> + BaseMemoryLib
>
> + DebugLib
>
> + FileHandleLib
>
> + HiiLib
>
> + HttpLib
>
> + MemoryAllocationLib
>
> + NetLib
>
> + ShellLib
>
> + UefiApplicationEntryPoint
>
> + UefiBootServicesTableLib
>
> + UefiHiiServicesLib
>
> + UefiLib
>
> + UefiRuntimeServicesTableLib
>
> +
>
> +[Protocols]
>
> + gEfiHiiPackageListProtocolGuid ## CONSUMES
>
> + gEfiHttpProtocolGuid ## CONSUMES
>
> + gEfiHttpServiceBindingProtocolGuid ## CONSUMES
>
> + gEfiManagedNetworkServiceBindingProtocolGuid ## CONSUMES
>
> diff --git
> a/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.c
> b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.c
> new file mode 100644
> index 000000000000..ba654749a075
> --- /dev/null
> +++
> b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.c
> @@ -0,0 +1,134 @@
> +/** @file
>
> + Produce "http" shell dynamic command.
>
> +
>
> + Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
<BR>
>
> + Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
>
> + Copyright (c) 2020, Broadcom. All rights reserved.<BR>
>
> +
>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +#include <Protocol/ShellDynamicCommand.h>
>
> +#include "Http.h"
>
> +
>
> +/**
>
> + This is the shell command handler function pointer callback type.
This
>
> + function handles the command when it is invoked in the shell.
>
> +
>
> + @param[in] This The instance of the
>
> + EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.
>
> + @param[in] SystemTable The pointer to the system table.
>
> + @param[in] ShellParameters The parameters associated with the
command.
>
> + @param[in] Shell The instance of the shell protocol used
in
>
> + the context of processing this command.
>
> +
>
> + @return EFI_SUCCESS the operation was sucessful
>
> + @return other the operation failed.
>
> +**/
>
> +SHELL_STATUS
>
> +EFIAPI
>
> +HttpCommandHandler (
>
> + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,
>
> + IN EFI_SYSTEM_TABLE *SystemTable,
>
> + IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
>
> + IN EFI_SHELL_PROTOCOL *Shell
>
> + )
>
> +{
>
> + gEfiShellParametersProtocol = ShellParameters;
>
> + gEfiShellProtocol = Shell;
>
> +
>
> + return RunHttp (gImageHandle, SystemTable);
>
> +}
>
> +
>
> +/**
>
> + This is the command help handler function pointer callback type.
This
>
> + function is responsible for displaying help information for the
associated
>
> + command.
>
> +
>
> + @param[in] This The instance of the
> EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.
>
> + @param[in] Language The pointer to the language string to use.
>
> +
>
> + @return string Pool allocated help string, must be freed by
caller
>
> +**/
>
> +CHAR16 *
>
> +EFIAPI
>
> +HttpCommandGetHelp (
>
> + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,
>
> + IN CONST CHAR8 *Language
>
> + )
>
> +{
>
> + return HiiGetString(mHttpHiiHandle,
>
> + STRING_TOKEN (STR_GET_HELP_HTTP),
>
> + Language);
>
> +}
>
> +
>
> +EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mHttpDynamicCommand = {
>
> + HTTP_APP_NAME,
>
> + HttpCommandHandler,
>
> + HttpCommandGetHelp
>
> +};
>
> +
>
> +/**
>
> + Entry point of Http Dynamic Command.
>
> +
>
> + Produce the DynamicCommand protocol to handle "http" command.
>
> +
>
> + @param ImageHandle The image handle of the process.
>
> + @param SystemTable The EFI System Table pointer.
>
> +
>
> + @retval EFI_SUCCESS Http command is executed sucessfully.
>
> + @retval EFI_ABORTED HII package was failed to initialize.
>
> + @retval others Other errors when executing http
command.
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +HttpCommandInitialize (
>
> + IN EFI_HANDLE ImageHandle,
>
> + IN EFI_SYSTEM_TABLE *SystemTable
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> +
>
> + mHttpHiiHandle = InitializeHiiPackage (ImageHandle);
>
> + if (mHttpHiiHandle == NULL) {
>
> + return EFI_ABORTED;
>
> + }
>
> +
>
> + Status = gBS->InstallProtocolInterface (
>
> + &ImageHandle,
>
> + &gEfiShellDynamicCommandProtocolGuid,
>
> + EFI_NATIVE_INTERFACE,
>
> + &mHttpDynamicCommand
>
> + );
>
> + ASSERT_EFI_ERROR (Status);
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Http driver unload handler.
>
> +
>
> + @param ImageHandle The image handle of the process.
>
> +
>
> + @retval EFI_SUCCESS The image is unloaded.
>
> + @retval Others Failed to unload the image.
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +HttpUnload (
>
> + IN EFI_HANDLE ImageHandle
>
> +)
>
> +{
>
> + EFI_STATUS Status;
>
> + Status = gBS->UninstallProtocolInterface (
>
> + ImageHandle,
>
> + &gEfiShellDynamicCommandProtocolGuid,
>
> + &mHttpDynamicCommand
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + return Status;
>
> + }
>
> +
>
> + HiiRemovePackages (mHttpHiiHandle);
>
> +
>
> + return EFI_SUCCESS;
>
> +}
>
> diff --git
> a/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.in
> f
> b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.in
> f
> new file mode 100644
> index 000000000000..5d46ee2384d5
> --- /dev/null
> +++
> b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.in
> f
> @@ -0,0 +1,63 @@
> +## @file
>
> +# Provides Shell 'http' dynamic command.
>
> +#
>
> +# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.
<BR>
>
> +# Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
>
> +# Copyright (c) 2020, Broadcom. All rights reserved.<BR>
>
> +#
>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +#
>
> +#
>
> +##
>
> +
>
> +[Defines]
>
> + INF_VERSION = 0x00010006
>
> + BASE_NAME = httpDynamicCommand
>
> + FILE_GUID = 19618BCE-55AE-09C6-37E9-4CE04084C7A1
>
> + MODULE_TYPE = DXE_DRIVER
>
> + VERSION_STRING = 1.0
>
> + ENTRY_POINT = HttpCommandInitialize
>
> + UNLOAD_IMAGE = HttpUnload
>
> +#
>
> +# This flag specifies whether HII resource section is generated into
PE image.
>
> +#
>
> + UEFI_HII_RESOURCE_SECTION = TRUE
>
> +
>
> +[Sources.common]
>
> + Http.c
>
> + HttpDynamicCommand.c
>
> + Http.h
>
> + Http.uni
>
> +
>
> +[Packages]
>
> + EmbeddedPkg/EmbeddedPkg.dec
>
> + MdePkg/MdePkg.dec
>
> + MdeModulePkg/MdeModulePkg.dec
>
> + NetworkPkg/NetworkPkg.dec
>
> + ShellPkg/ShellPkg.dec
>
> +
>
> +[LibraryClasses]
>
> + BaseLib
>
> + BaseMemoryLib
>
> + DebugLib
>
> + FileHandleLib
>
> + HiiLib
>
> + HttpLib
>
> + MemoryAllocationLib
>
> + NetLib
>
> + ShellLib
>
> + UefiBootServicesTableLib
>
> + UefiDriverEntryPoint
>
> + UefiHiiServicesLib
>
> + UefiLib
>
> + UefiRuntimeServicesTableLib
>
> +
>
> +[Protocols]
>
> + gEfiHiiPackageListProtocolGuid ## CONSUMES
>
> + gEfiHttpProtocolGuid ## CONSUMES
>
> + gEfiHttpServiceBindingProtocolGuid ## CONSUMES
>
> + gEfiManagedNetworkServiceBindingProtocolGuid ## CONSUMES
>
> + gEfiShellDynamicCommandProtocolGuid ## PRODUCES
>
> +
>
> +[DEPEX]
>
> + TRUE
>
> diff --git a/ShellPkg/Include/Guid/ShellLibHiiGuid.h
> b/ShellPkg/Include/Guid/ShellLibHiiGuid.h
> index 5da9128333a4..6e328b460d8c 100644
> --- a/ShellPkg/Include/Guid/ShellLibHiiGuid.h
> +++ b/ShellPkg/Include/Guid/ShellLibHiiGuid.h
> @@ -59,6 +59,10 @@
> 0x738a9314, 0x82c1, 0x4592, { 0x8f, 0xf7, 0xc1, 0xbd, 0xf1, 0xb2,
0x0e, 0xd4 }
> \
>
> }
>
>
>
> +#define SHELL_HTTP_HII_GUID \
>
> + { \
>
> + 0x390f84b3, 0x221c, 0x4d9e, { 0xb5, 0x06, 0x6d, 0xb9, 0x42, 0x3e,
0x0a,
> 0x7e } \
>
> + }
>
>
>
> #define SHELL_BCFG_HII_GUID \
>
> { \
>
> @@ -75,6 +79,7 @@ extern EFI_GUID gShellLevel3HiiGuid;
> extern EFI_GUID gShellNetwork1HiiGuid;
>
> extern EFI_GUID gShellNetwork2HiiGuid;
>
> extern EFI_GUID gShellTftpHiiGuid;
>
> +extern EFI_GUID gShellHttpHiiGuid;
>
> extern EFI_GUID gShellBcfgHiiGuid;
>
>
>
> #endif
>
> diff --git a/ShellPkg/ShellPkg.dec b/ShellPkg/ShellPkg.dec
> index c17e358d15ed..f80a2962dfd1 100644
> --- a/ShellPkg/ShellPkg.dec
> +++ b/ShellPkg/ShellPkg.dec
> @@ -50,6 +50,7 @@ [Guids]
> gShellNetwork1HiiGuid = {0xf3d301bb, 0xf4a5, 0x45a8, {0xb0,
0xb7, 0xfa,
> 0x99, 0x9c, 0x62, 0x37, 0xae}}
>
> gShellNetwork2HiiGuid = {0x174b2b5, 0xf505, 0x4b12, {0xaa,
0x60, 0x59,
> 0xdf, 0xf8, 0xd6, 0xea, 0x37}}
>
> gShellTftpHiiGuid = {0x738a9314, 0x82c1, 0x4592, {0x8f,
0xf7, 0xc1,
> 0xbd, 0xf1, 0xb2, 0x0e, 0xd4}}
>
> + gShellHttpHiiGuid = {0x390f84b3, 0x221c, 0x4d9e, {0xb5,
0x06, 0x6d,
> 0xb9, 0x42, 0x3e, 0x0a, 0x7e}}
>
> gShellBcfgHiiGuid = {0x5f5f605d, 0x1583, 0x4a2d, {0xa6,
0xb2, 0xeb,
> 0x12, 0xda, 0xb4, 0xa2, 0xb6}}
>
> gShellAcpiViewHiiGuid = {0xda8ccdf4, 0xed8f, 0x4ffc, {0xb5,
0xef, 0x2e,
> 0xf5, 0x5e, 0x24, 0x93, 0x2a}}
>
> # FILE_GUID as defined in ShellPkg/Application/Shell/Shell.inf
>
> diff --git a/ShellPkg/ShellPkg.dsc b/ShellPkg/ShellPkg.dsc
> index b7ee856b3a16..58aa6e12bea3 100644
> --- a/ShellPkg/ShellPkg.dsc
> +++ b/ShellPkg/ShellPkg.dsc
> @@ -138,6 +138,11 @@ [Components]
> gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
>
> }
>
> ShellPkg/DynamicCommand/TftpDynamicCommand/TftpApp.inf
>
> +
> ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf {
>
> + <PcdsFixedAtBuild>
>
> + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
>
> + }
>
> + ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
>
> ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf {
>
> <PcdsFixedAtBuild>
>
> gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
>
> --
> 2.26.2.266.ge870325ee8
>
>
> -=-=-=-=-=-=
> Groups.io Links: You receive all messages sent to this group.
>
> View/Reply Online (#59160): https://edk2.groups.io/g/devel/message/59160
> Mute This Topic: https://groups.io/mt/74141905/1768756
> Group Owner: devel+owner@edk2.groups.io
> Unsubscribe: https://edk2.groups.io/g/devel/unsub
[zhichao.gao@intel.com]
> -=-=-=-=-=-=
prev parent reply other threads:[~2020-07-03 3:47 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-11 18:03 [PATCH v2 1/1] ShellPkg/DynamicCommand: add HttpDynamicCommand Vladimir Olovyannikov
2020-07-02 5:55 ` [edk2-devel] " Gao, Zhichao
2020-07-03 3:47 ` Vladimir Olovyannikov [this message]
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=8d65606f6a71a40624ab22868b743530@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