From: "Vladimir Olovyannikov" <vladimir.olovyannikov@broadcom.com>
To: "Gao, Liming" <liming.gao@intel.com>,
devel@edk2.groups.io, "Gao, Zhichao" <zhichao.gao@intel.com>,
samer.el-haj-mahmoud@arm.com, "Ni, Ray" <ray.ni@intel.com>,
"Fu, Siyuan" <siyuan.fu@intel.com>,
"Wu, Jiaxin" <jiaxin.wu@intel.com>,
Maciej Rabeda <maciej.rabeda@linux.intel.com>
Cc: nd <nd@arm.com>
Subject: Re: [edk2-devel] [PATCH 1/1] ShellPkg/DynamicCommand: add HttpDynamicCommand
Date: Fri, 8 May 2020 11:10:34 -0700 [thread overview]
Message-ID: <599fc568fc52a786ee3f8c584761b498@mail.gmail.com> (raw)
In-Reply-To: <BN6PR11MB3972CF76FDBD8CDC4268A16F80A20@BN6PR11MB3972.namprd11.prod.outlook.com>
I have a newer version which supports the functionality discussed earlier.
Please review it once I post the update.
Thank you,
Vladimir
-----Original Message-----
From: Gao, Liming <liming.gao@intel.com>
Sent: Friday, May 8, 2020 8:58 AM
To: devel@edk2.groups.io; Gao, Zhichao <zhichao.gao@intel.com>;
samer.el-haj-mahmoud@arm.com; Vladimir Olovyannikov
<vladimir.olovyannikov@broadcom.com>; Ni, Ray <ray.ni@intel.com>; Fu, Siyuan
<siyuan.fu@intel.com>; Wu, Jiaxin <jiaxin.wu@intel.com>; Maciej Rabeda
<maciej.rabeda@linux.intel.com>
Cc: nd <nd@arm.com>; Gao, Liming <liming.gao@intel.com>
Subject: RE: [edk2-devel] [PATCH 1/1] ShellPkg/DynamicCommand: add
HttpDynamicCommand
Include Maciej for network part.
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Gao,
> Zhichao
> Sent: Friday, May 8, 2020 11:56 PM
> To: devel@edk2.groups.io; samer.el-haj-mahmoud@arm.com; Vladimir
> Olovyannikov <vladimir.olovyannikov@broadcom.com>; Ni,
> Ray <ray.ni@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>; Wu, Jiaxin
> <jiaxin.wu@intel.com>
> Cc: nd <nd@arm.com>
> Subject: Re: [edk2-devel] [PATCH 1/1] ShellPkg/DynamicCommand: add
> HttpDynamicCommand
>
> I think the NetworkPkg maintainer can give a better comment and the remain
> part of the implementation need their help to review.
>
> Hi Jiaxin/Siyuan,
>
> Do you have any comments on this? And the implementation is part of
> NetworkPkg protocol usage. I am not familiar with this. Please
> help to review.
>
> Thanks,
> Zhichao
>
> > -----Original Message-----
> > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Samer El-
> > Haj-Mahmoud
> > Sent: Friday, May 8, 2020 5:54 PM
> > To: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>;
> > devel@edk2.groups.io; Ni, Ray <ray.ni@intel.com>; Gao, Zhichao
> > <zhichao.gao@intel.com>
> > Cc: nd <nd@arm.com>
> > Subject: Re: [edk2-devel] [PATCH 1/1] ShellPkg/DynamicCommand: add
> > HttpDynamicCommand
> >
> > Any update on this patch? This is a useful command to add to the Shell
> > (for both
> > testing and deployment/scripting).
> >
> > > -----Original Message-----
> > > From: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>
> > > Sent: Tuesday, April 21, 2020 1:37 PM
> > > To: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>;
> > > devel@edk2.groups.io; Ray Ni <ray.ni@intel.com>; Zhichao Gao
> > > <zhichao.gao@intel.com>
> > > Cc: nd <nd@arm.com>
> > > Subject: RE: [edk2-devel] [PATCH 1/1] ShellPkg/DynamicCommand: add
> > > HttpDynamicCommand
> > >
> > > .. Skipped..
> > > > Thanks Vladimir for the explanation.
> > > >
> > > > Wondering what is more useful to users:
> > > >
> > > > 1- Having the 'http' and 'tftp' commands share a common interface
> > > > to
> > > > make
> > > > it easier to script using either tool/protocol (as explained below)
> > > > Or
> > > > 2- Having a more natural support for URIs in 'http' command,
> > > > similar to
> > > > what
> > > > is common in other http CLI clients like curl
> > > >
> > > > If (1) is important enough for users, then could we entertain adding
> > > > (2)
> > > > in
> > > > addition to (1).
> > > Thank you for the feedback Samer,
> > > Well, (1) is important for us as we use universal UEFI Shell scripts
> > > for
> > > multiple images updates from any media (usb, network(http/tftp), etc.)
> > > I agree that adding (2) to (1) makes sense. Would be nice to get more
> > > feedback from edk2 community on that.
> > >
> > > Thank you,
> > > Vladimir
> > > >
> > > > Thanks,
> > > > --Samer
> > > >
> > > >
> > > > > -----Original Message-----
> > > > > From: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>
> > > > > Sent: Monday, April 20, 2020 1:10 PM
> > > > > To: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>;
> > > > > devel@edk2.groups.io; Ray Ni <ray.ni@intel.com>; Zhichao Gao
> > > > > <zhichao.gao@intel.com>
> > > > > Cc: nd <nd@arm.com>
> > > > > Subject: RE: [edk2-devel] [PATCH 1/1] ShellPkg/DynamicCommand: add
> > > > > HttpDynamicCommand
> > > > >
> > > > > Hi Samer,
> > > > > > -----Original Message-----
> > > > > > From: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>
> > > > > > Sent: Sunday, April 19, 2020 5:31 AM
> > > > > > To: devel@edk2.groups.io; vladimir.olovyannikov@broadcom.com;
> > > Ray
> > > > Ni
> > > > > > <ray.ni@intel.com>; Zhichao Gao <zhichao.gao@intel.com>
> > > > > > Cc: nd <nd@arm.com>
> > > > > > Subject: RE: [edk2-devel] [PATCH 1/1] ShellPkg/DynamicCommand:
> > > > > > add
> > > > > > HttpDynamicCommand
> > > > > >
> > > > > > Tested-By: Samer El-Haj-Mahmoud <Samer.El-Haj-
> > > Mahmoud@arm.com>
> > > > > >
> > > > > > I tested on Aarch64 (RPi4) and the command seems to work well.
> > > > > >
> > > > > > One question: why is the input arguments "host[:port]" and the
> > > > > > remote
> > > > > file
> > > > > > "http_uri" not treated as a single "http_uri" argument?
> > > > > >
> > > > > > For example, instead of:
> > > > > > fs0:\> http http://192.168.1.1:8080 dir1/file1.dat file2.dat
> > > > > >
> > > > > > Why not:
> > > > > > fs0:\> http http://192.168.1.1:8080/dir1/file1.dat file2.dat
> > > > > The idea was to make it 100% compatible with tftp command.
> > > > > This way, one could easily support both in one script like this:
> > > > > set -v eth_int " -i eth0"
> > > > > ...
> > > > > # Set update protocol on some low-level init
> > > > > set upd_proto http (or tftp, or something else if needed and
> > > > > supported)
> > > > > ...
> > > > > # Set protocol-specific parameters
> > > > > if "%u_proto%" == "tftp" then
> > > > > set -v tftp_blk_param " -s %tftp_blocksize%"
> > > > > set -v tftp_win_param " -w %tftp_windowsize%"
> > > > > endif
> > > > > ...
> > > > > # "Universalize" transfer command
> > > > > set -v transfer_cmd "%u_proto% %eth_int% %tftp_blk_param%
> > > > > %tftp_win_param%
> > > > > %serverip% %tftp_dir%"
> > > > > ...
> > > > > # Use universal transfer command with no changes for any update
> > > protocol
> > > > > (be it tftp, http, etc.).
> > > > > %transfer_cmd%/md5sum.txt %esp_root%\md5sum.txt
> > > > > ...
> > > > >
> > > > > Thanks,
> > > > > Vladimir
> > > > > >
> > > > > >
> > > > > >
> > > > > > > -----Original Message-----
> > > > > > > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of
> > > > > > Vladimir
> > > > > > > Olovyannikov via Groups.Io
> > > > > > > Sent: Friday, January 24, 2020 7:57 PM
> > > > > > > To: devel@edk2.groups.io; Ray Ni <ray.ni@intel.com>; Zhichao
> > > > > > > Gao
> > > > > > > <zhichao.gao@intel.com>
> > > > > > > Cc: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>
> > > > > > > Subject: [edk2-devel] [PATCH 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 x30 times 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>
> > > > > > > ---
> > > > > > > .../DynamicCommand/HttpDynamicCommand/Http.c | 1639
> > > > > > > +++++++++++++++++
> > > > > > > .../DynamicCommand/HttpDynamicCommand/Http.h | 88 +
> > > > > > > .../HttpDynamicCommand/Http.uni | 95 +
> > > > > > > .../HttpDynamicCommand/HttpApp.c | 53 +
> > > > > > > .../HttpDynamicCommand/HttpApp.inf | 58 +
> > > > > > > .../HttpDynamicCommand/HttpDynamicCommand.c | 134 ++
> > > > > > > .../HttpDynamicCommand/HttpDynamicCommand.inf | 63 +
> > > > > > > ShellPkg/Include/Guid/ShellLibHiiGuid.h | 7 +-
> > > > > > > ShellPkg/ShellPkg.dec | 1 +
> > > > > > > ShellPkg/ShellPkg.dsc | 5 +
> > > > > > > 10 files changed, 2142 insertions(+), 1 deletion(-)
> > > > > > > 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
> > > > > > .in
> > > > > > > f
> > > > > > >
> > > > > > > diff --git
> > > a/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c
> > > > > > > b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c
> > > > > > > new file mode 100644
> > > > > > > index 000000000000..4e0af3417348
> > > > > > > --- /dev/null
> > > > > > > +++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c
> > > > > > > @@ -0,0 +1,1639 @@
> > > > > > > +/** @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 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;
> > > > > > > +
> > > > > > > +/**
> > > > > > > + 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 a
> > > > > > > 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"-p", 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;
> > > > > > > + CONST CHAR16 *ProxyServerAddr;
> > > > > > > + EFI_HTTP_CONFIG_DATA HttpConfigData;
> > > > > > > + EFI_HTTPv4_ACCESS_POINT IPv4Node;
> > > > > > > + EFI_HANDLE *Handles;
> > > > > > > + UINTN HandleCount;
> > > > > > > + UINTN NicNumber;
> > > > > > > + UINTN InitialSize;
> > > > > > > + CHAR16
> > > > > > > NicName[IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH];
> > > > > > > + EFI_HANDLE ControllerHandle;
> > > > > > > + EFI_HANDLE HttpChildHandle;
> > > > > > > + DOWNLOAD_CONTEXT Context;
> > > > > > > +
> > > > > > > + ProblemParam = NULL;
> > > > > > > + NicFound = FALSE;
> > > > > > > + Handles = NULL;
> > > > > > > +
> > > > > > > + //
> > > > > > > + // Initialize the Shell library (we must be in
> > > > > > > non-auto-init...)
> > > > > > > + //
> > > > > > > + 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 > 4) {
> > > > > > > + ShellPrintHiiEx (
> > > > > > > + -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY),
> > > > > > > + mHttpHiiHandle, HTTP_APP_NAME
> > > > > > > + );
> > > > > > > + goto Error;
> > > > > > > + }
> > > > > > > +
> > > > > > > + if (ParamCount < 3) {
> > > > > > > + 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;
> > > > > > > +
> > > > > > > + 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"://")
> > > > > > > + );
> > > > > > > + }
> > > > > > > +
> > > > > > > + Context.ServerAddrAndProto = StrnCatGrow (
> > > > > > > +
> > > > > > > &Context.ServerAddrAndProto,
> > > > > > > + &StartSize,
> > > > > > > + ValueStr,
> > > > > > > + StrLen (ValueStr)
> > > > > > > + );
> > > > > > > + if (!Context.ServerAddrAndProto) {
> > > > > > > + Status = EFI_OUT_OF_RESOURCES;
> > > > > > > + goto Error;
> > > > > > > + }
> > > > > > > + }
> > > > > > > +
> > > > > > > + RemoteFilePath = ShellCommandLineGetRawValue (CheckPackage,
> > > > 2);
> > > > > > > + ASSERT (RemoteFilePath != NULL);
> > > > > > > + if (RemoteFilePath) {
> > > > > > > + TrimSpaces ((CHAR16 **)&RemoteFilePath);
> > > > > > > + } else {
> > > > > > > + Status = EFI_INVALID_PARAMETER;
> > > > > > > + goto Error;
> > > > > > > + }
> > > > > > > +
> > > > > > > + if (ParamCount == 4) {
> > > > > > > + mLocalFilePath = ShellCommandLineGetRawValue
> > > > > > > (CheckPackage,
> > > > 3);
> > > > > > > + } 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;
> > > > > > > + }
> > > > > > > + }
> > > > > > > +
> > > > > > > + // Is proxy server used?
> > > > > > > + ProxyServerAddr = ShellCommandLineGetValue (CheckPackage,
> > > > > > > L"-
> > > > p");
> > > > > > > + if (ProxyServerAddr) {
> > > > > > > + UINTN StringSize;
> > > > > > > +
> > > > > > > + StringSize = StrLen (ProxyServerAddr) + 1;
> > > > > > > + Context.ProxyServerAddr = AllocatePool (StringSize);
> > > > > > > + if (!Context.ProxyServerAddr) {
> > > > > > > + Status = EFI_OUT_OF_RESOURCES;
> > > > > > > + goto Error;
> > > > > > > + }
> > > > > > > + UnicodeStrToAsciiStrS (
> > > > > > > + ProxyServerAddr,
> > > > > > > + Context.ProxyServerAddr,
> > > > > > > + StringSize
> > > > > > > + );
> > > > > > > + }
> > > > > > > +
> > > > > > > + Context.BufferSize = DEFAULT_BUF_SIZE;
> > > > > > > +
> > > > > > > + // By default, the buffer size is 1M. This can be changed
> > > > > > > with -s
> > > > > > parameter.
> > > > > > > + 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 = 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
> > > > > > > + );
> > > > > > > + goto NextHandle;
> > > > > > > + }
> > > > > > > +
> > > > > > > + 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;
> > > > > > > + }
> > > > > > > +
> > > > > > > + goto NextHandle;
> > > > > > > + }
> > > > > > > +
> > > > > > > + Status = EFI_SUCCESS;
> > > > > > > +
> > > > > > > +NextHandle:
> > > > > > > + if (Status == EFI_HTTP_ERROR) {
> > > > > > > + goto Error;
> > > > > > > + }
> > > > > > > + }
> > > > > > > +
> > > > > > > + 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.ProxyServerAddr);
> > > > > > > + 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;
> > > > > > > +
> > > > > > > + ZeroMem (&RequestData, sizeof (RequestData));
> > > > > > > + ZeroMem (&RequestHeader, sizeof (RequestHeader));
> > > > > > > + ZeroMem (&RequestMessage, sizeof (RequestMessage));
> > > > > > > + ZeroMem (&Context->RequestToken, sizeof (Context-
> > > > > > >RequestToken));
> > > > > > > +
> > > > > > > + RequestHeader.FieldName = "Host";
> > > > > > > + if (Context->ProxyServerAddr) {
> > > > > > > + RequestHeader.FieldValue = Context->ProxyServerAddr;
> > > > > > > + } else {
> > > > > > > + CHAR16 *Host;
> > > > > > > + UINTN StringSize;
> > > > > > > +
> > > > > > > + 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;
> > > > > > > + CHAR8 *Tmp;
> > > > > > > + CHAR16 *Url;
> > > > > > > +
> > > > > > > + Tmp = NULL;
> > > > > > > + Url = NULL;
> > > > > > > +
> > > > > > > + 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 (AsciiStrStr (Location, "://")) {
> > > > > > > + CHAR8 *Walker;
> > > > > > > + UINTN Idx;
> > > > > > > + UINTN Step;
> > > > > > > +
> > > > > > > + Idx = 0;
> > > > > > > + Walker = Location;
> > > > > > > +
> > > > > > > + for (Step = 0; 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);
> > > > > > > +
> > > > > > > + Context->ServerAddrAndProto = AllocateZeroPool
> > > > > > > (StringSize);
> > > > > > > + if (!Context->ServerAddrAndProto) {
> > > > > > > + Status = EFI_OUT_OF_RESOURCES;
> > > > > > > + goto Error;
> > > > > > > + }
> > > > > > > +
> > > > > > > + Status = AsciiStrToUnicodeStrS (
> > > > > > > + (CONST CHAR8 *)Tmp,
> > > > > > > + Context->ServerAddrAndProto,
> > > > > > > + StringSize
> > > > > > > + );
> > > > > > > + if (EFI_ERROR (Status)) {
> > > > > > > + 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;
> > > > > > > + }
> > > > > > > +
> > > > > > > + 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 (Context->Status != REQ_ERROR) {
> > > > > > > + Context->Status = REQ_ERROR;
> > > > > > > + ShellPrintHiiEx (
> > > > > > > + -1, -1, NULL, STRING_TOKEN
> > > > > (STR_HTTP_ERR_STATUSCODE),
> > > > > > > + mHttpHiiHandle,
> > > > > > > Context->ServerAddrAndProto,
> > > > > > > + ErrStatusDesc[ResponseData.StatusCode -
> > > > > > > +
> > > > > > > HTTP_STATUS_400_BAD_REQUEST],
> > > > > > > + Context->URI
> > > > > > > + );
> > > > > > > + }
> > > > > > > + }
> > > > > > > + }
> > > > > > > +
> > > > > > > + // 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 download the data of a file from a
> > > > > > > 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 (EFI_ERROR (Status)) {
> > > > > > > + goto ON_EXIT;
> > > > > > > + }
> > > > > > > +
> > > > > > > + Status = GetResponse (Context, DownloadUrl);
> > > > > > > +
> > > > > > > + if (EFI_ERROR (Status)) {
> > > > > > > + goto ON_EXIT;
> > > > > > > + }
> > > > > > > + } while (Context->Status == REQ_NEED_REPEAT);
> > > > > > > +
> > > > > > > + if (Context->Status == REQ_ERROR) {
> > > > > > > + Status = EFI_HTTP_ERROR;
> > > > > > > + }
> > > > > > > +
> > > > > > > +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..daebe9cf1731
> > > > > > > --- /dev/null
> > > > > > > +++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h
> > > > > > > @@ -0,0 +1,88 @@
> > > > > > > +/** @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"
> > > > > > > +
> > > > > > > +extern EFI_HII_HANDLE mHttpHiiHandle;
> > > > > > > +
> > > > > > > +typedef enum {
> > > > > > > + REQ_OK = 0,
> > > > > > > + REQ_NEED_REPEAT = 1,
> > > > > > > + REQ_ERROR = 2
> > > > > > > +} REQ_STATUS;
> > > > > > > +
> > > > > > > +typedef struct {
> > > > > > > + UINTN ContentDownloaded;
> > > > > > > + UINTN ContentLength;
> > > > > > > + UINTN LastReportedNbOfBytes;
> > > > > > > + UINTN BufferSize;
> > > > > > > + REQ_STATUS Status;
> > > > > > > + UINT8 *Buffer;
> > > > > > > + CHAR8 *ProxyServerAddr;
> > > > > > > + 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..ab62ffacb812
> > > > > > > --- /dev/null
> > > > > > > +++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni
> > > > > > > @@ -0,0 +1,95 @@
> > > > > > > +// /**
> > > > > > > +//
> > > > > > > +// (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>]\r\n"
> > > > > > > +" host[:port] http_uri [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"
> > > > > > > +" -t <timeout> - The number of seconds to wait for a
> > > > > > > response
> > > > > > after\r\n"
> > > > > > > +" sending a request packet. Default value
> > > > > > > is 0
> > > > > which is
> > > > > > > 'automatic'.\r\n"
> > > > > > > +" host - Specify HTTP Server IPv4 address.\r\n
> > > > > > > + Can be either 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"
> > > > > > > +" 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"
> > > > > > > +".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
> > > > > > > as
> > > > > localfilepath
> > > > > > parameter."
> > > > > > > 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/HttpDynamicComma
> > > > > > nd.
> > > > > > > c
> > > > > > >
> > > > > >
> > > >
> > > b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma
> > > > > > nd.
> > > > > > > c
> > > > > > > new file mode 100644
> > > > > > > index 000000000000..ba654749a075
> > > > > > > --- /dev/null
> > > > > > > +++
> > > > > > >
> > > > > >
> > > >
> > > b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma
> > > > > > nd.
> > > > > > > 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/HttpDynamicComma
> > > > > > nd.
> > > > > > > inf
> > > > > > >
> > > > > >
> > > >
> > > b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma
> > > > > > nd.
> > > > > > > inf
> > > > > > > new file mode 100644
> > > > > > > index 000000000000..5d46ee2384d5
> > > > > > > --- /dev/null
> > > > > > > +++
> > > > > > >
> > > > > >
> > > >
> > > b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma
> > > > > > nd.
> > > > > > > inf
> > > > > > > @@ -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..d5f2ceac07a9 100644
> > > > > > > --- a/ShellPkg/Include/Guid/ShellLibHiiGuid.h
> > > > > > > +++ b/ShellPkg/Include/Guid/ShellLibHiiGuid.h
> > > > > > > @@ -58,7 +58,11 @@
> > > > > > > { \
> > > > > > > 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 91493400cab7..aee00245185d 100644
> > > > > > > --- a/ShellPkg/ShellPkg.dsc
> > > > > > > +++ b/ShellPkg/ShellPkg.dsc
> > > > > > > @@ -137,6 +137,11 @@ [Components]
> > > > > > >
> > > > > > > gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
> > > > > > > }
> > > > > > > ShellPkg/DynamicCommand/TftpDynamicCommand/TftpApp.inf
> > > > > > > +
> > > > > > >
> > > > > >
> > > >
> > > ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand
> > > > > > .in
> > > > > > > f {
> > > > > > > + <PcdsFixedAtBuild>
> > > > > > > +
> > > > > > > gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
> > > > > > > + }
> > > > > > > + ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
> > > > > > >
> > > > > >
> > > >
> > > ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf
> > > > > > > {
> > > > > > > <PcdsFixedAtBuild>
> > > > > > >
> > > > > > > gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
> > > > > > > --
> > > > > > > 2.17.1
> > > > > > >
> > > > > > >
> > > > > > >
> >
> >
>
>
>
prev parent reply other threads:[~2020-05-08 18:10 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-01-25 0:57 [PATCH 1/1] ShellPkg/DynamicCommand: add HttpDynamicCommand Vladimir Olovyannikov
2020-04-16 6:56 ` Gao, Zhichao
2020-05-11 16:38 ` [edk2-devel] " Vladimir Olovyannikov
2020-04-19 12:30 ` Samer El-Haj-Mahmoud
2020-04-20 17:10 ` Vladimir Olovyannikov
2020-04-21 16:49 ` Samer El-Haj-Mahmoud
2020-04-21 17:37 ` Vladimir Olovyannikov
2020-05-08 9:53 ` Samer El-Haj-Mahmoud
2020-05-08 15:56 ` Gao, Zhichao
2020-05-08 15:58 ` Liming Gao
2020-05-08 18:10 ` 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=599fc568fc52a786ee3f8c584761b498@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