On 09/29/20 04:29, Gao, Zhichao wrote:
> Hi,
> 
> I have checked in openCI and it is passed.
> 
> Reviewed-by: Zhichao Gao <zhichao....@intel.com>
> 
> Hi Laszlo,
> 
> Do you have a plan to test this patch?

Yep, I've been watching this thread as well. I'm happy that you are OK
with v13, and so v13 is about to be merged. It's a great feature.

Tested-by: Laszlo Ersek <ler...@redhat.com>

Thanks!
Laszlo

>> -----Original Message-----
>> From: Vladimir Olovyannikov <vladimir.olovyanni...@broadcom.com>
>> Sent: Friday, September 25, 2020 4:41 AM
>> To: devel@edk2.groups.io
>> Cc: Vladimir Olovyannikov <vladimir.olovyanni...@broadcom.com>; Samer El-
>> Haj-Mahmoud <samer.el-haj-mahm...@arm.com>; Laszlo Ersek
>> <ler...@redhat.com>; Gao, Zhichao <zhichao....@intel.com>; Maciej Rabeda
>> <maciej.rab...@linux.intel.com>; Wu, Jiaxin <jiaxin...@intel.com>; Fu, Siyuan
>> <siyuan...@intel.com>; Ni, Ray <ray...@intel.com>; Liming Gao
>> <liming....@intel.com>; Nd <n...@arm.com>
>> Subject: [PATCH v13 1/1] ShellPkg/DynamicCommand: add
>> HttpDynamicCommand
>>
>> Introduce an http client utilizing EDK2 HTTP protocol, to
>> allow fast image downloading from http/https servers.
>> HTTP download speed is usually faster than tftp.
>> The client is based on the same approach as tftp dynamic command, and
>> uses the same UEFI Shell command line parameters. This makes it easy
>> integrating http into existing UEFI Shell scripts.
>> Note that to enable HTTP download, feature Pcd
>> gEfiNetworkPkgTokenSpaceGuid.PcdAllowHttpConnections must
>> be set to TRUE.
>> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2860
>>
>> Signed-off-by: Vladimir Olovyannikov <vladimir.olovyanni...@broadcom.com>
>> Cc: Samer El-Haj-Mahmoud <samer.el-haj-mahm...@arm.com>
>> Cc: Laszlo Ersek <ler...@redhat.com>
>> Cc: Zhichao Gao <zhichao....@intel.com>
>> Cc: Maciej Rabeda <maciej.rab...@linux.intel.com>
>> Cc: Jiaxin Wu <jiaxin...@intel.com>
>> Cc: Siyuan Fu <siyuan...@intel.com>
>> Cc: Ray Ni <ray...@intel.com>
>> Cc: Liming Gao <liming....@intel.com>
>> Cc: Nd <n...@arm.com>
>> ---
>>  ShellPkg/ShellPkg.dec                         |    1 +
>>  ShellPkg/ShellPkg.dsc                         |    5 +
>>  .../HttpDynamicCommand/HttpApp.inf            |   57 +
>>  .../HttpDynamicCommand/HttpDynamicCommand.inf |   62 +
>>  .../DynamicCommand/HttpDynamicCommand/Http.h  |   92 +
>>  ShellPkg/Include/Guid/ShellLibHiiGuid.h       |    5 +
>>  .../DynamicCommand/HttpDynamicCommand/Http.c  | 1904
>> +++++++++++++++++
>>  .../HttpDynamicCommand/HttpApp.c              |   61 +
>>  .../HttpDynamicCommand/HttpDynamicCommand.c   |  137 ++
>>  .../HttpDynamicCommand/Http.uni               |  117 +
>>  10 files changed, 2441 insertions(+)
>>  create mode 100644
>> ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
>>  create mode 100644
>> ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf
>>  create mode 100644
>> ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h
>>  create mode 100644 ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c
>>  create mode 100644
>> ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c
>>  create mode 100644
>> ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.c
>>  create mode 100644
>> ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni
>>
>> diff --git a/ShellPkg/ShellPkg.dec b/ShellPkg/ShellPkg.dec
>> index d0843d338126..7b2d1230bd2c 100644
>> --- a/ShellPkg/ShellPkg.dec
>> +++ b/ShellPkg/ShellPkg.dec
>> @@ -53,6 +53,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 86e9f1e0040d..c42bc9464a0f 100644
>> --- a/ShellPkg/ShellPkg.dsc
>> +++ b/ShellPkg/ShellPkg.dsc
>> @@ -139,6 +139,11 @@ [Components]
>>        gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
>>    }
>>    ShellPkg/DynamicCommand/TftpDynamicCommand/TftpApp.inf
>> +
>> ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf {
>> +    <PcdsFixedAtBuild>
>> +      gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
>> +  }
>> +  ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
>>    ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf {
>>      <PcdsFixedAtBuild>
>>        gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
>> diff --git a/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
>> b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
>> new file mode 100644
>> index 000000000000..27b208b25437
>> --- /dev/null
>> +++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
>> @@ -0,0 +1,57 @@
>> +##  @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]
>> +  MdeModulePkg/MdeModulePkg.dec
>> +  MdePkg/MdePkg.dec
>> +  NetworkPkg/NetworkPkg.dec
>> +  ShellPkg/ShellPkg.dec
>> +
>> +[LibraryClasses]
>> +  BaseLib
>> +  BaseMemoryLib
>> +  DebugLib
>> +  FileHandleLib
>> +  HiiLib
>> +  HttpLib
>> +  MemoryAllocationLib
>> +  NetLib
>> +  ShellLib
>> +  UefiApplicationEntryPoint
>> +  UefiBootServicesTableLib
>> +  UefiHiiServicesLib
>> +  UefiLib
>> +  UefiRuntimeServicesTableLib
>> +
>> +[Protocols]
>> +  gEfiHiiPackageListProtocolGuid                 ## CONSUMES
>> +  gEfiHttpProtocolGuid                         ## CONSUMES
>> +  gEfiHttpServiceBindingProtocolGuid           ## CONSUMES
>> +  gEfiManagedNetworkServiceBindingProtocolGuid   ## CONSUMES
>> diff --git
>> a/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.in
>> f
>> b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.in
>> f
>> new file mode 100644
>> index 000000000000..159cae214ccc
>> --- /dev/null
>> +++
>> b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.in
>> f
>> @@ -0,0 +1,62 @@
>> +##  @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]
>> +  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/DynamicCommand/HttpDynamicCommand/Http.h
>> b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h
>> new file mode 100644
>> index 000000000000..fa8b6f5aa4e5
>> --- /dev/null
>> +++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h
>> @@ -0,0 +1,92 @@
>> +/** @file
>> +  Header file for 'http' command functions.
>> +
>> +  Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved. <BR>
>> +  Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
>> +  Copyright (c) 2020, Broadcom. All rights reserved.<BR>
>> +
>> +  SPDX-License-Identifier: BSD-2-Clause-Patent
>> +
>> +**/
>> +
>> +#ifndef _HTTP_H_
>> +#define _HTTP_H_
>> +
>> +#include <Uefi.h>
>> +
>> +#include <Library/BaseLib.h>
>> +#include <Library/BaseMemoryLib.h>
>> +#include <Library/DebugLib.h>
>> +#include <Library/HiiLib.h>
>> +#include <Library/HttpLib.h>
>> +#include <Library/MemoryAllocationLib.h>
>> +#include <Library/NetLib.h>
>> +#include <Library/PrintLib.h>
>> +#include <Library/ShellLib.h>
>> +#include <Library/UefiBootServicesTableLib.h>
>> +#include <Library/UefiHiiServicesLib.h>
>> +#include <Library/UefiLib.h>
>> +#include <Library/UefiRuntimeServicesTableLib.h>
>> +
>> +#include <Protocol/HiiPackageList.h>
>> +#include <Protocol/HttpUtilities.h>
>> +#include <Protocol/ServiceBinding.h>
>> +
>> +#define HTTP_APP_NAME L"http"
>> +
>> +#define REQ_OK           0
>> +#define REQ_NEED_REPEAT  1
>> +
>> +//
>> +// Download Flags.
>> +//
>> +#define DL_FLAG_TIME     BIT0 // Show elapsed time.
>> +#define DL_FLAG_KEEP_BAD BIT1 // Keep files even if download failed.
>> +
>> +extern EFI_HII_HANDLE mHttpHiiHandle;
>> +
>> +typedef struct {
>> +  UINTN                 ContentDownloaded;
>> +  UINTN                 ContentLength;
>> +  UINTN                 LastReportedNbOfBytes;
>> +  UINTN                 BufferSize;
>> +  UINTN                 Status;
>> +  UINTN                 Flags;
>> +  UINT8                 *Buffer;
>> +  CHAR16                *ServerAddrAndProto;
>> +  CHAR16                *Uri;
>> +  EFI_HTTP_TOKEN        ResponseToken;
>> +  EFI_HTTP_TOKEN        RequestToken;
>> +  EFI_HTTP_PROTOCOL     *Http;
>> +  EFI_HTTP_CONFIG_DATA  HttpConfigData;
>> +} 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
>> +  );
>> +
>> +/**
>> +  Retrieve HII package list from ImageHandle and publish to HII database.
>> +
>> +  @param[in] ImageHandle            The image handle of the process.
>> +
>> +  @retval HII handle.
>> +**/
>> +EFI_HII_HANDLE
>> +InitializeHiiPackage (
>> +  IN EFI_HANDLE                  ImageHandle
>> +  );
>> +#endif // _HTTP_H_
>> diff --git a/ShellPkg/Include/Guid/ShellLibHiiGuid.h
>> b/ShellPkg/Include/Guid/ShellLibHiiGuid.h
>> index 5da9128333a4..6e328b460d8c 100644
>> --- a/ShellPkg/Include/Guid/ShellLibHiiGuid.h
>> +++ b/ShellPkg/Include/Guid/ShellLibHiiGuid.h
>> @@ -59,6 +59,10 @@
>>      0x738a9314, 0x82c1, 0x4592, { 0x8f, 0xf7, 0xc1, 0xbd, 0xf1, 0xb2, 0x0e, 
>> 0xd4 }
>> \
>>    }
>>
>> +#define SHELL_HTTP_HII_GUID \
>> +  { \
>> +    0x390f84b3, 0x221c, 0x4d9e, { 0xb5, 0x06, 0x6d, 0xb9, 0x42, 0x3e, 0x0a,
>> 0x7e } \
>> +  }
>>
>>  #define SHELL_BCFG_HII_GUID \
>>    { \
>> @@ -75,6 +79,7 @@ extern EFI_GUID gShellLevel3HiiGuid;
>>  extern EFI_GUID gShellNetwork1HiiGuid;
>>  extern EFI_GUID gShellNetwork2HiiGuid;
>>  extern EFI_GUID gShellTftpHiiGuid;
>> +extern EFI_GUID gShellHttpHiiGuid;
>>  extern EFI_GUID gShellBcfgHiiGuid;
>>
>>  #endif
>> diff --git a/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c
>> b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c
>> new file mode 100644
>> index 000000000000..3735a4a7e645
>> --- /dev/null
>> +++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c
>> @@ -0,0 +1,1904 @@
>> +/** @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
>> +
>> +//
>> +// Constant strings and definitions related to the message
>> +// indicating the amount of progress in the dowloading of a HTTP file.
>> +//
>> +
>> +//
>> +// Number of steps in the progression slider.
>> +//
>> +#define HTTP_PROGRESS_SLIDER_STEPS  \
>> +  ((sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) - 3)
>> +
>> +//
>> +// Size in number of characters plus one (final zero) of the message to
>> +// indicate the progress of an HTTP download. The format is "[(progress 
>> slider:
>> +// 40 characters)] (nb of KBytes downloaded so far: 7 characters) Kb". There
>> +// are thus the number of characters in HTTP_PROGR_FRAME[] plus 11
>> characters
>> +// (2 // spaces, "Kb" and seven characters for the number of KBytes).
>> +//
>> +#define HTTP_PROGRESS_MESSAGE_SIZE  \
>> +  ((sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) + 12)
>> +
>> +//
>> +// Buffer size. Note that larger buffer does not mean better speed.
>> +//
>> +#define DEFAULT_BUF_SIZE      SIZE_32KB
>> +#define MAX_BUF_SIZE          SIZE_4MB
>> +
>> +#define MIN_PARAM_COUNT       2
>> +#define MAX_PARAM_COUNT       4
>> +#define NEED_REDIRECTION(Code) \
>> +  (((Code >= HTTP_STATUS_300_MULTIPLE_CHOICES) \
>> +  && (Code <= HTTP_STATUS_307_TEMPORARY_REDIRECT)) \
>> +  || (Code == HTTP_STATUS_308_PERMANENT_REDIRECT))
>> +
>> +#define CLOSE_HTTP_HANDLE(ControllerHandle,HttpChildHandle) \
>> +  do { \
>> +    if (HttpChildHandle) { \
>> +      CloseProtocolAndDestroyServiceChild ( \
>> +        ControllerHandle, \
>> +        &gEfiHttpServiceBindingProtocolGuid, \
>> +        &gEfiHttpProtocolGuid, \
>> +        HttpChildHandle \
>> +        ); \
>> +      HttpChildHandle = NULL; \
>> +    } \
>> +  } while (0)
>> +
>> +typedef enum {
>> +  HdrHost,
>> +  HdrConn,
>> +  HdrAgent,
>> +  HdrMax
>> +} HDR_TYPE;
>> +
>> +#define USER_AGENT_HDR  "Mozilla/5.0 (EDK2; Linux) Gecko/20100101
>> Firefox/79.0"
>> +
>> +#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"[                                        ]"
>> +
>> +//
>> +// Improve readability by using these macros.
>> +//
>> +#define PRINT_HII(token,...) \
>> +  ShellPrintHiiEx (\
>> +      -1, -1, NULL, token, mHttpHiiHandle, __VA_ARGS__)
>> +
>> +#define PRINT_HII_APP(token,value) \
>> +  PRINT_HII (token, HTTP_APP_NAME, value)
>> +
>> +//
>> +// TimeBaseLib.h constants.
>> +// These will be removed once the library gets fixed.
>> +//
>> +
>> +//
>> +// Define EPOCH (1970-JANUARY-01) in the Julian Date representation.
>> +//
>> +#define EPOCH_JULIAN_DATE                               2440588
>> +
>> +//
>> +// Seconds per unit.
>> +//
>> +#define SEC_PER_MIN                                     ((UINTN)    60)
>> +#define SEC_PER_HOUR                                    ((UINTN)  3600)
>> +#define SEC_PER_DAY                                     ((UINTN) 86400)
>> +
>> +//
>> +// 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"
>> +};
>> +
>> +STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
>> +  {L"-i", TypeValue},
>> +  {L"-k", TypeFlag},
>> +  {L"-l", TypeValue},
>> +  {L"-m", TypeFlag},
>> +  {L"-s", TypeValue},
>> +  {L"-t", TypeValue},
>> +  {NULL , TypeMax}
>> +};
>> +
>> +//
>> +// Local File Handle.
>> +//
>> +STATIC SHELL_FILE_HANDLE   mFileHandle = NULL;
>> +
>> +//
>> +// Path of the local file, Unicode encoded.
>> +//
>> +STATIC CONST CHAR16        *mLocalFilePath;
>> +
>> +STATIC BOOLEAN             gRequestCallbackComplete = FALSE;
>> +STATIC BOOLEAN             gResponseCallbackComplete = FALSE;
>> +
>> +STATIC BOOLEAN             gHttpError;
>> +
>> +EFI_HII_HANDLE             mHttpHiiHandle;
>> +
>> +//
>> +// Functions declarations.
>> +//
>> +
>> +/**
>> +  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.
>> +
>> +  @retval     TRUE      The value was returned.
>> +  @retval     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.
>> +
>> +  @retval  EFI_SUCCESS  The name of the NIC was returned.
>> +  @retval  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.
>> +
>> +  @retval  EFI_SUCCESS  The child was created and the protocol opened.
>> +  @retval  Others       Either the creation of the child or the opening
>> +                        of the protocol failed.
>> +**/
>> +STATIC
>> +EFI_STATUS
>> +CreateServiceChildAndOpenProtocol (
>> +  IN   EFI_HANDLE  ControllerHandle,
>> +  IN   EFI_GUID    *ServiceBindingProtocolGuid,
>> +  IN   EFI_GUID    *ProtocolGuid,
>> +  OUT  EFI_HANDLE  *ChildHandle,
>> +  OUT  VOID        **Interface
>> +  );
>> +
>> +/**
>> +  Close the protocol identified by its GUID on the child handle of the 
>> service
>> +  identified by its service binding protocol GUID, then destroy the child
>> +  handle.
>> +
>> +  @param[in]  ControllerHandle            Controller handle.
>> +  @param[in]  ServiceBindingProtocolGuid  Service binding protocol GUID of 
>> the
>> +                                          service to be destroyed.
>> +  @param[in]  ProtocolGuid                GUID of the protocol to be closed.
>> +  @param[in]  ChildHandle                 Handle of the child to be 
>> destroyed.
>> +
>> +**/
>> +STATIC
>> +VOID
>> +CloseProtocolAndDestroyServiceChild (
>> +  IN  EFI_HANDLE  ControllerHandle,
>> +  IN  EFI_GUID    *ServiceBindingProtocolGuid,
>> +  IN  EFI_GUID    *ProtocolGuid,
>> +  IN  EFI_HANDLE  ChildHandle
>> +  );
>> +
>> +/**
>> +  Worker function that download the data of a file from an HTTP server given
>> +  the path of the file and its size.
>> +
>> +  @param[in]   Context           A pointer to the download context.
>> +
>> +  @retval  EFI_SUCCESS           The file was downloaded.
>> +  @retval  EFI_OUT_OF_RESOURCES  A memory allocation failed.
>> +  @retval  Others                The downloading of the file
>> +                                 from the server failed.
>> +**/
>> +STATIC
>> +EFI_STATUS
>> +DownloadFile (
>> +  IN   HTTP_DOWNLOAD_CONTEXT   *Context,
>> +  IN   EFI_HANDLE              ControllerHandle,
>> +  IN   CHAR16                  *NicName
>> +  );
>> +
>> +/**
>> +  Cleans off leading and trailing spaces and tabs.
>> +
>> +  @param[in]                      String pointer to the string to trim them 
>> off.
>> +
>> +  @retval EFI_SUCCESS             No errors.
>> +  @retval EFI_INVALID_PARAMETER   String pointer is NULL.
>> +**/
>> +STATIC
>> +EFI_STATUS
>> +TrimSpaces (
>> +  IN CHAR16 *String
>> +  )
>> +{
>> +  CHAR16 *Str;
>> +  UINTN  Len;
>> +
>> +  ASSERT (String != NULL);
>> +
>> +  if (String == NULL) {
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  Str = String;
>> +
>> +  //
>> +  // Remove any whitespace at the beginning of the Str.
>> +  //
>> +  while (*Str == L' ' || *Str == L'\t') {
>> +    Str++;
>> +  }
>> +
>> +  //
>> +  // Remove any whitespace at the end of the Str.
>> +  //
>> +  do {
>> +    Len = StrLen (Str);
>> +    if (!Len || (Str[Len - 1] != L' ' && Str[Len - 1] != '\t')) {
>> +      break;
>> +    }
>> +
>> +    Str[Len - 1] = CHAR_NULL;
>> +  } while (Len);
>> +
>> +  CopyMem (String, Str, StrSize (Str));
>> +
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +//
>> +// Callbacks for request and response.
>> +// We just acknowledge that operation has completed here.
>> +//
>> +
>> +/**
>> +  Callback to set the request completion flag.
>> +
>> +  @param[in] Event:   The event.
>> +  @param[in] Context: pointer to Notification Context.
>> + **/
>> +STATIC
>> +VOID
>> +EFIAPI
>> +RequestCallback (
>> +  IN EFI_EVENT Event,
>> +  IN VOID      *Context
>> +  )
>> +{
>> +  gRequestCallbackComplete = TRUE;
>> +}
>> +
>> +/**
>> +  Callback to set the response completion flag.
>> +  @param[in] Event:   The event.
>> +  @param[in] Context: pointer to Notification Context.
>> + **/
>> +STATIC
>> +VOID
>> +EFIAPI
>> +ResponseCallback (
>> +  IN EFI_EVENT Event,
>> +  IN VOID      *Context
>> +  )
>> +{
>> +  gResponseCallbackComplete = TRUE;
>> +}
>> +
>> +//
>> +// Set of functions from TimeBaseLib.
>> +// This will be removed once TimeBaseLib is enabled for ShellPkg.
>> +//
>> +
>> +/**
>> +  Calculate Epoch days.
>> +
>> +  @param[in] Time - a pointer to the EFI_TIME abstraction.
>> +
>> +  @retval           Number of days elapsed since EPOCH_JULIAN_DAY.
>> + **/
>> +STATIC
>> +UINTN
>> +EfiGetEpochDays (
>> +  IN  EFI_TIME  *Time
>> +  )
>> +{
>> +  UINTN a;
>> +  UINTN y;
>> +  UINTN m;
>> +  //
>> +  // Absolute Julian Date representation of the supplied Time.
>> +  //
>> +  UINTN JulianDate;
>> +  //
>> +  // Number of days elapsed since EPOCH_JULIAN_DAY.
>> +  //
>> +  UINTN EpochDays;
>> +
>> +  a = (14 - Time->Month) / 12 ;
>> +  y = Time->Year + 4800 - a;
>> +  m = Time->Month + (12 * a) - 3;
>> +
>> +  JulianDate = Time->Day + ((153 * m + 2) / 5) + (365 * y) + (y / 4) -
>> +               (y / 100) + (y / 400) - 32045;
>> +
>> +  ASSERT (JulianDate >= EPOCH_JULIAN_DATE);
>> +  EpochDays = JulianDate - EPOCH_JULIAN_DATE;
>> +
>> +  return EpochDays;
>> +}
>> +
>> +/**
>> +  Converts EFI_TIME to Epoch seconds
>> +  (elapsed since 1970 JANUARY 01, 00:00:00 UTC).
>> +
>> +  @param[in] Time: a pointer to EFI_TIME abstraction.
>> + **/
>> +STATIC
>> +UINTN
>> +EFIAPI
>> +EfiTimeToEpoch (
>> +  IN  EFI_TIME  *Time
>> +  )
>> +{
>> +  //
>> +  // Number of days elapsed since EPOCH_JULIAN_DAY.
>> +  //
>> +  UINTN EpochDays;
>> +  UINTN EpochSeconds;
>> +
>> +  EpochDays = EfiGetEpochDays (Time);
>> +
>> +  EpochSeconds = (EpochDays * SEC_PER_DAY) +
>> +                 ((UINTN)Time->Hour * SEC_PER_HOUR) +
>> +                 (Time->Minute * SEC_PER_MIN) + Time->Second;
>> +
>> +  return EpochSeconds;
>> +}
>> +
>> +/**
>> +  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).
>> +
>> +  @retval  SHELL_SUCCESS            The 'http' command completed 
>> successfully.
>> +  @retval  SHELL_ABORTED            The Shell Library initialization failed.
>> +  @retval  SHELL_INVALID_PARAMETER  At least one of the command's
>> arguments is
>> +                                    not valid.
>> +  @retval  SHELL_OUT_OF_RESOURCES   A memory allocation failed.
>> +  @retval  SHELL_NOT_FOUND          Network Interface Card not found.
>> +  @retval  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;
>> +  UINTN                   ParamCount;
>> +  UINTN                   HandleCount;
>> +  UINTN                   NicNumber;
>> +  UINTN                   InitialSize;
>> +  UINTN                   ParamOffset;
>> +  UINTN                   StartSize;
>> +  CHAR16                  *ProblemParam;
>> +  CHAR16                  NicName[IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH];
>> +  CHAR16                  *Walker1;
>> +  CHAR16                  *VStr;
>> +  CONST CHAR16            *UserNicName;
>> +  CONST CHAR16            *ValueStr;
>> +  CONST CHAR16            *RemoteFilePath;
>> +  CONST CHAR16            *Walker;
>> +  EFI_HTTPv4_ACCESS_POINT IPv4Node;
>> +  EFI_HANDLE              *Handles;
>> +  EFI_HANDLE              ControllerHandle;
>> +  HTTP_DOWNLOAD_CONTEXT   Context;
>> +  BOOLEAN                 NicFound;
>> +
>> +  ProblemParam        = NULL;
>> +  RemoteFilePath      = NULL;
>> +  NicFound            = FALSE;
>> +  Handles             = NULL;
>> +
>> +  //
>> +  // Initialize the Shell library (we must be in non-auto-init...).
>> +  //
>> +  ParamOffset = 0;
>> +  gHttpError  = FALSE;
>> +
>> +  Status = ShellInitialize ();
>> +  if (EFI_ERROR (Status)) {
>> +    ASSERT_EFI_ERROR (Status);
>> +    return SHELL_ABORTED;
>> +  }
>> +
>> +  ZeroMem (&Context, sizeof (Context));
>> +
>> +  //
>> +  // Parse the command line.
>> +  //
>> +  Status = ShellCommandLineParse (
>> +             ParamList,
>> +             &CheckPackage,
>> +             &ProblemParam,
>> +             TRUE
>> +             );
>> +  if (EFI_ERROR (Status)) {
>> +    if ((Status == EFI_VOLUME_CORRUPTED)
>> +     && (ProblemParam != NULL))
>> +    {
>> +      PRINT_HII_APP (STRING_TOKEN (STR_GEN_PROBLEM), ProblemParam);
>> +      SHELL_FREE_NON_NULL (ProblemParam);
>> +    } else {
>> +      ASSERT (FALSE);
>> +    }
>> +
>> +    goto Error;
>> +  }
>> +
>> +  //
>> +  // Check the number of parameters.
>> +  //
>> +  Status = EFI_INVALID_PARAMETER;
>> +
>> +  ParamCount = ShellCommandLineGetCount (CheckPackage);
>> +  if (ParamCount > MAX_PARAM_COUNT) {
>> +    PRINT_HII_APP (STRING_TOKEN (STR_GEN_TOO_MANY), NULL);
>> +    goto Error;
>> +  }
>> +
>> +  if (ParamCount < MIN_PARAM_COUNT) {
>> +    PRINT_HII_APP (STRING_TOKEN (STR_GEN_TOO_FEW), NULL);
>> +    goto Error;
>> +  }
>> +
>> +  ZeroMem (&Context.HttpConfigData, sizeof (Context.HttpConfigData));
>> +  ZeroMem (&IPv4Node, sizeof (IPv4Node));
>> +  IPv4Node.UseDefaultAddress = TRUE;
>> +
>> +  Context.HttpConfigData.HttpVersion = HttpVersion11;
>> +  Context.HttpConfigData.AccessPoint.IPv4Node = &IPv4Node;
>> +
>> +  //
>> +  // Get the host address (not necessarily IPv4 format).
>> +  //
>> +  ValueStr = ShellCommandLineGetRawValue (CheckPackage, 1);
>> +  if (!ValueStr) {
>> +    PRINT_HII_APP (STRING_TOKEN (STR_GEN_PARAM_INV), ValueStr);
>> +    goto Error;
>> +  } else {
>> +    StartSize = 0;
>> +    TrimSpaces ((CHAR16 *)ValueStr);
>> +    if (!StrStr (ValueStr, L"://")) {
>> +      Context.ServerAddrAndProto = StrnCatGrow (
>> +                                     &Context.ServerAddrAndProto,
>> +                                     &StartSize,
>> +                                     DEFAULT_HTTP_PROTO,
>> +                                     StrLen (DEFAULT_HTTP_PROTO)
>> +                                     );
>> +      Context.ServerAddrAndProto = StrnCatGrow (
>> +                                     &Context.ServerAddrAndProto,
>> +                                     &StartSize,
>> +                                     L"://",
>> +                                     StrLen (L"://")
>> +                                     );
>> +      VStr = (CHAR16 *)ValueStr;
>> +    } else {
>> +      VStr = StrStr (ValueStr, L"://") + StrLen (L"://");
>> +    }
>> +
>> +    for (Walker1 = VStr; *Walker1; Walker1++) {
>> +      if (*Walker1 == L'/') {
>> +        break;
>> +      }
>> +    }
>> +
>> +    if (*Walker1 == L'/') {
>> +      ParamOffset = 1;
>> +      RemoteFilePath = Walker1;
>> +    }
>> +
>> +    Context.ServerAddrAndProto = StrnCatGrow (
>> +                                   &Context.ServerAddrAndProto,
>> +                                   &StartSize,
>> +                                   ValueStr,
>> +                                   StrLen (ValueStr) - StrLen (Walker1)
>> +                                   );
>> +    if (!Context.ServerAddrAndProto) {
>> +      Status = EFI_OUT_OF_RESOURCES;
>> +      goto Error;
>> +    }
>> +  }
>> +
>> +  if (!RemoteFilePath) {
>> +    RemoteFilePath = ShellCommandLineGetRawValue (CheckPackage, 2);
>> +    if (!RemoteFilePath) {
>> +      //
>> +      // If no path given, assume just "/".
>> +      //
>> +      RemoteFilePath = L"/";
>> +    }
>> +  }
>> +
>> +  TrimSpaces ((CHAR16 *)RemoteFilePath);
>> +
>> +  if (ParamCount == MAX_PARAM_COUNT - ParamOffset) {
>> +    mLocalFilePath = ShellCommandLineGetRawValue (
>> +                       CheckPackage,
>> +                       MAX_PARAM_COUNT - 1 - ParamOffset
>> +                       );
>> +  } else {
>> +    Walker = RemoteFilePath + StrLen (RemoteFilePath);
>> +    while ((--Walker) >= RemoteFilePath) {
>> +      if ((*Walker == L'\\') ||
>> +          (*Walker == L'/' )    ) {
>> +        break;
>> +      }
>> +    }
>> +
>> +    mLocalFilePath = Walker + 1;
>> +  }
>> +
>> +  if (!StrLen (mLocalFilePath)) {
>> +    mLocalFilePath = DEFAULT_HTML_FILE;
>> +  }
>> +
>> +  InitialSize = 0;
>> +  Context.Uri = StrnCatGrow (
>> +                  &Context.Uri,
>> +                  &InitialSize,
>> +                  RemoteFilePath,
>> +                  StrLen (RemoteFilePath)
>> +                  );
>> +  if (!Context.Uri) {
>> +    Status = EFI_OUT_OF_RESOURCES;
>> +    goto Error;
>> +  }
>> +
>> +  //
>> +  // Get the name of the Network Interface Card to be used if any.
>> +  //
>> +  UserNicName = ShellCommandLineGetValue (CheckPackage, L"-i");
>> +
>> +  ValueStr = ShellCommandLineGetValue (CheckPackage, L"-l");
>> +  if ((ValueStr != NULL)
>> +   && (!StringToUint16 (
>> +          ValueStr,
>> +          &Context.HttpConfigData.AccessPoint.IPv4Node->LocalPort
>> +          )
>> +      ))
>> +  {
>> +    goto Error;
>> +  }
>> +
>> +  Context.BufferSize = DEFAULT_BUF_SIZE;
>> +
>> +  ValueStr = ShellCommandLineGetValue (CheckPackage, L"-s");
>> +  if (ValueStr != NULL) {
>> +    Context.BufferSize = ShellStrToUintn (ValueStr);
>> +    if (!Context.BufferSize || Context.BufferSize > MAX_BUF_SIZE) {
>> +      PRINT_HII_APP (STRING_TOKEN (STR_GEN_PARAM_INV), ValueStr);
>> +      goto Error;
>> +    }
>> +  }
>> +
>> +  ValueStr = ShellCommandLineGetValue (CheckPackage, L"-t");
>> +  if (ValueStr != NULL) {
>> +    Context.HttpConfigData.TimeOutMillisec = (UINT32)ShellStrToUintn
>> (ValueStr);
>> +  }
>> +
>> +  //
>> +  // Locate all HTTP Service Binding protocols.
>> +  //
>> +  Status = gBS->LocateHandleBuffer (
>> +                  ByProtocol,
>> +                  &gEfiManagedNetworkServiceBindingProtocolGuid,
>> +                  NULL,
>> +                  &HandleCount,
>> +                  &Handles
>> +                  );
>> +  if (EFI_ERROR (Status) || (HandleCount == 0)) {
>> +    PRINT_HII (STRING_TOKEN (STR_HTTP_ERR_NO_NIC), NULL);
>> +    if (!EFI_ERROR (Status)) {
>> +      Status = EFI_NOT_FOUND;
>> +    }
>> +
>> +    goto Error;
>> +  }
>> +
>> +  Status = EFI_NOT_FOUND;
>> +
>> +  Context.Flags = 0;
>> +  if (ShellCommandLineGetFlag (CheckPackage, L"-m")) {
>> +    Context.Flags |= DL_FLAG_TIME;
>> +  }
>> +
>> +  if (ShellCommandLineGetFlag (CheckPackage, L"-k")) {
>> +    Context.Flags |= DL_FLAG_KEEP_BAD;
>> +  }
>> +
>> +  for (NicNumber = 0;
>> +       (NicNumber < HandleCount) && (Status != EFI_SUCCESS);
>> +       NicNumber++)
>> +  {
>> +    ControllerHandle = Handles[NicNumber];
>> +
>> +    Status = GetNicName (ControllerHandle, NicNumber, NicName);
>> +    if (EFI_ERROR (Status)) {
>> +      PRINT_HII (STRING_TOKEN (STR_HTTP_ERR_NIC_NAME), NicNumber,
>> Status);
>> +      continue;
>> +    }
>> +
>> +    if (UserNicName != NULL) {
>> +      if (StrCmp (NicName, UserNicName) != 0) {
>> +        Status = EFI_NOT_FOUND;
>> +        continue;
>> +      }
>> +
>> +      NicFound = TRUE;
>> +    }
>> +
>> +    Status = DownloadFile (&Context, ControllerHandle, NicName);
>> +    PRINT_HII (STRING_TOKEN (STR_GEN_CRLF), NULL);
>> +
>> +    if (EFI_ERROR (Status)) {
>> +      PRINT_HII (
>> +        STRING_TOKEN (STR_HTTP_ERR_DOWNLOAD),
>> +        RemoteFilePath,
>> +        NicName,
>> +        Status
>> +        );
>> +      //
>> +      // If a user aborted the operation,
>> +      // do not try another controller.
>> +      //
>> +      if (Status == EFI_ABORTED) {
>> +        goto Error;
>> +      }
>> +    }
>> +
>> +    if (gHttpError) {
>> +     //
>> +     // This is not related to connection, so no need to repeat with
>> +     // another interface.
>> +     //
>> +      break;
>> +    }
>> +  }
>> +
>> +  if ((UserNicName != NULL) && (!NicFound)) {
>> +    PRINT_HII (STRING_TOKEN (STR_HTTP_ERR_NIC_NOT_FOUND),
>> UserNicName);
>> +  }
>> +
>> +Error:
>> +  ShellCommandLineFreeVarList (CheckPackage);
>> +  SHELL_FREE_NON_NULL (Handles);
>> +  SHELL_FREE_NON_NULL (Context.ServerAddrAndProto);
>> +  SHELL_FREE_NON_NULL (Context.Uri);
>> +
>> +  return Status & ~MAX_BIT;
>> +}
>> +
>> +/**
>> +  Check and convert the UINT16 option values of the 'http' command
>> +
>> +  @param[in]  ValueStr  Value as an Unicode encoded string
>> +  @param[out] Value     UINT16 value
>> +
>> +  @retval     TRUE      The value was returned.
>> +  @retval     FALSE     A parsing error occured.
>> +**/
>> +STATIC
>> +BOOLEAN
>> +StringToUint16 (
>> +  IN   CONST CHAR16  *ValueStr,
>> +  OUT  UINT16        *Value
>> +  )
>> +{
>> +  UINTN  Val;
>> +
>> +  Val = ShellStrToUintn (ValueStr);
>> +  if (Val > MAX_UINT16) {
>> +    PRINT_HII_APP (STRING_TOKEN (STR_GEN_PARAM_INV), 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.
>> +
>> +  @retval  EFI_SUCCESS  The name of the NIC was returned.
>> +  @retval  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.
>> +
>> +  @retval  EFI_SUCCESS  The child was created and the protocol opened.
>> +  @retval  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, out]  CallBackComplete   A pointer to the callback completion
>> +                                      variable set by the callback.
>> +
>> +  @retval  EFI_SUCCESS                Callback signalled completion.
>> +  @retval  EFI_TIMEOUT                Timed out waiting for completion.
>> +  @retval  Others                     Error waiting for completion.
>> +**/
>> +STATIC
>> +EFI_STATUS
>> +WaitForCompletion (
>> +  IN HTTP_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);
>> +    if (!Context->ContentDownloaded
>> +     && CallBackComplete == &gResponseCallbackComplete)
>> +    {
>> +      //
>> +      // An HTTP server may just send a response redirection header.
>> +      // In this case, don't wait for the event as
>> +      // it might never happen and we waste 10s waiting.
>> +      // Note that at this point Response may not has been populated,
>> +      // so it needs to be checked first.
>> +      //
>> +      if (Context->ResponseToken.Message
>> +       && Context->ResponseToken.Message->Data.Response
>> +       && (NEED_REDIRECTION (
>> +            Context->ResponseToken.Message->Data.Response->StatusCode
>> +            )
>> +         ))
>> +      {
>> +        break;
>> +      }
>> +    }
>> +  }
>> +
>> +  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.
>> +
>> +  @retval EFI_SUCCESS            Request has been sent successfully.
>> +  @retval EFI_INVALID_PARAMETER  Invalid URL.
>> +  @retval EFI_OUT_OF_RESOURCES   Out of memory.
>> +  @retval EFI_DEVICE_ERROR       If HTTPS is used, this probably
>> +                                 means that TLS support either was not
>> +                                 installed or not configured.
>> +  @retval Others                 Error sending the request.
>> +**/
>> +STATIC
>> +EFI_STATUS
>> +SendRequest (
>> +  IN HTTP_DOWNLOAD_CONTEXT  *Context,
>> +  IN CHAR16                 *DownloadUrl
>> +  )
>> +{
>> +  EFI_HTTP_REQUEST_DATA       RequestData;
>> +  EFI_HTTP_HEADER             RequestHeader[HdrMax];
>> +  EFI_HTTP_MESSAGE            RequestMessage;
>> +  EFI_STATUS                  Status;
>> +  CHAR16                      *Host;
>> +  UINTN                       StringSize;
>> +
>> +  ZeroMem (&RequestData, sizeof (RequestData));
>> +  ZeroMem (&RequestHeader, sizeof (RequestHeader));
>> +  ZeroMem (&RequestMessage, sizeof (RequestMessage));
>> +  ZeroMem (&Context->RequestToken, sizeof (Context->RequestToken));
>> +
>> +  RequestHeader[HdrHost].FieldName = "Host";
>> +  RequestHeader[HdrConn].FieldName = "Connection";
>> +  RequestHeader[HdrAgent].FieldName = "User-Agent";
>> +
>> +  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[HdrHost].FieldValue = AllocatePool (StringSize);
>> +  if (!RequestHeader[HdrHost].FieldValue) {
>> +    return EFI_OUT_OF_RESOURCES;
>> +  }
>> +
>> +  UnicodeStrToAsciiStrS (
>> +    Host,
>> +    RequestHeader[HdrHost].FieldValue,
>> +    StringSize
>> +    );
>> +
>> +  RequestHeader[HdrConn].FieldValue = "close";
>> +  RequestHeader[HdrAgent].FieldValue = USER_AGENT_HDR;
>> +  RequestMessage.HeaderCount = HdrMax;
>> +
>> +  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[HdrHost].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 HTTP_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) {
>> +      PRINT_HII (STRING_TOKEN (STR_GEN_CRLF), NULL);
>> +    }
>> +
>> +    PRINT_HII (STRING_TOKEN (STR_HTTP_ERR_WRITE), 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.
>> +
>> +  @retval  EFI_SUCCESS            Host and Uri were successfully set.
>> +  @retval  EFI_OUT_OF_RESOURCES   Error setting Host or Uri.
>> +**/
>> +STATIC
>> +EFI_STATUS
>> +SetHostURI (
>> +  IN CHAR8                 *Location,
>> +  IN HTTP_DOWNLOAD_CONTEXT *Context,
>> +  IN CHAR16                *DownloadUrl
>> +  )
>> +{
>> +  EFI_STATUS    Status;
>> +  UINTN         StringSize;
>> +  UINTN         FirstStep;
>> +  UINTN         Idx;
>> +  UINTN         Step;
>> +  CHAR8         *Walker;
>> +  CHAR16        *Temp;
>> +  CHAR8         *Tmp;
>> +  CHAR16        *Url;
>> +  BOOLEAN       IsAbEmptyUrl;
>> +
>> +  Tmp = NULL;
>> +  Url = NULL;
>> +  IsAbEmptyUrl = FALSE;
>> +  FirstStep = 0;
>> +
>> +  StringSize = (AsciiStrSize (Location) * sizeof (CHAR16));
>> +  Url = AllocateZeroPool (StringSize);
>> +  if (!Url) {
>> +    return EFI_OUT_OF_RESOURCES;
>> +  }
>> +
>> +  Status = AsciiStrToUnicodeStrS (
>> +             (CONST CHAR8 *)Location,
>> +             Url,
>> +             StringSize
>> +             );
>> +
>> +  if (EFI_ERROR (Status)) {
>> +        goto Error;
>> +  }
>> +
>> +  //
>> +  // If an HTTP server redirects to the same location more than once,
>> +  // then stop attempts and tell it is not reachable.
>> +  //
>> +  if (!StrCmp (Url, DownloadUrl)) {
>> +    Status = EFI_NO_MAPPING;
>> +    goto Error;
>> +  }
>> +
>> +  if (AsciiStrLen (Location) > 2) {
>> +    //
>> +    // Some servers return 'Location: //server/resource'
>> +    //
>> +    IsAbEmptyUrl = (Location[0] == '/') && (Location[1] == '/');
>> +    if (IsAbEmptyUrl) {
>> +      //
>> +      // Skip first "//"
>> +      //
>> +      Location += 2;
>> +      FirstStep = 1;
>> +    }
>> +  }
>> +
>> +  if (AsciiStrStr (Location, "://") || IsAbEmptyUrl) {
>> +    Idx = 0;
>> +    Walker = Location;
>> +
>> +    for (Step = FirstStep; Step < 2; Step++) {
>> +      for (; *Walker != '/' && *Walker != '\0'; Walker++) {
>> +        Idx++;
>> +      }
>> +
>> +      if (!Step) {
>> +        //
>> +        // Skip "//"
>> +        //
>> +        Idx += 2;
>> +        Walker += 2;
>> +      }
>> +    }
>> +
>> +    Tmp = AllocateZeroPool (Idx + 1);
>> +    if (!Tmp) {
>> +      Status = EFI_OUT_OF_RESOURCES;
>> +      goto Error;
>> +    }
>> +
>> +    CopyMem (Tmp, Location, Idx);
>> +
>> +    //
>> +    // Location now points to Uri
>> +    //
>> +    Location += Idx;
>> +    StringSize = (Idx + 1) * sizeof (CHAR16);
>> +
>> +    SHELL_FREE_NON_NULL (Context->ServerAddrAndProto);
>> +
>> +    Temp = AllocateZeroPool (StringSize);
>> +    if (!Temp) {
>> +      Status = EFI_OUT_OF_RESOURCES;
>> +      goto Error;
>> +    }
>> +
>> +    Status = AsciiStrToUnicodeStrS (
>> +               (CONST CHAR8 *)Tmp,
>> +               Temp,
>> +               StringSize
>> +               );
>> +    if (EFI_ERROR (Status)) {
>> +      SHELL_FREE_NON_NULL (Temp);
>> +      goto Error;
>> +    }
>> +
>> +    Idx = 0;
>> +    if (IsAbEmptyUrl) {
>> +      Context->ServerAddrAndProto = StrnCatGrow (
>> +                                      &Context->ServerAddrAndProto,
>> +                                      &Idx,
>> +                                      L"http://";,
>> +                                      StrLen (L"http://";)
>> +                                      );
>> +    }
>> +
>> +    Context->ServerAddrAndProto = StrnCatGrow (
>> +                                    &Context->ServerAddrAndProto,
>> +                                    &Idx,
>> +                                    Temp,
>> +                                    StrLen (Temp)
>> +                                    );
>> +    SHELL_FREE_NON_NULL (Temp);
>> +    if (!Context->ServerAddrAndProto) {
>> +      Status = EFI_OUT_OF_RESOURCES;
>> +      goto Error;
>> +    }
>> +  }
>> +
>> +  SHELL_FREE_NON_NULL (Context->Uri);
>> +
>> +  StringSize = AsciiStrSize (Location) * sizeof (CHAR16);
>> +  Context->Uri = AllocateZeroPool (StringSize);
>> +  if (!Context->Uri) {
>> +    Status = EFI_OUT_OF_RESOURCES;
>> +    goto Error;
>> +  }
>> +
>> +  //
>> +  // Now make changes to the Uri part.
>> +  //
>> +  Status = AsciiStrToUnicodeStrS (
>> +             (CONST CHAR8 *)Location,
>> +             Context->Uri,
>> +             StringSize
>> +             );
>> +Error:
>> +  SHELL_FREE_NON_NULL (Tmp);
>> +  SHELL_FREE_NON_NULL (Url);
>> +
>> +  return Status;
>> +}
>> +
>> +/**
>> +  Message parser callback.
>> +  Save a portion of HTTP body.
>> +
>> +  @param[in]   EventType       Type of event. Can be either
>> +                               OnComplete or OnData.
>> +  @param[in]   Data            A pointer to the buffer with data.
>> +  @param[in]   Length          Data length of this portion.
>> +  @param[in]   Context         A pointer to the HTTP download context.
>> +
>> +  @retval      EFI_SUCCESS    The portion was processed successfully.
>> +  @retval      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 == NULL)
>> +   || (EventType == BodyParseEventOnComplete)
>> +   || (Context == NULL))
>> +  {
>> +    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]   DownloadUrl     A pointer to the fully qualified URL to 
>> download.
>> +
>> +  @retval  EFI_SUCCESS         Valid file. Body successfully collected.
>> +  @retval  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.
>> +  @retval Others               Error getting the reponse from the HTTP 
>> server.
>> +                               Response body is not collected.
>> +**/
>> +STATIC
>> +EFI_STATUS
>> +GetResponse (
>> +  IN HTTP_DOWNLOAD_CONTEXT    *Context,
>> +  IN CHAR16                   *DownloadUrl
>> +  )
>> +{
>> +  EFI_HTTP_RESPONSE_DATA      ResponseData;
>> +  EFI_HTTP_MESSAGE            ResponseMessage;
>> +  EFI_HTTP_HEADER             *Header;
>> +  EFI_STATUS                  Status;
>> +  VOID                        *MsgParser;
>> +  EFI_TIME                    StartTime;
>> +  EFI_TIME                    EndTime;
>> +  CONST CHAR16                *Desc;
>> +  UINTN                       ElapsedSeconds;
>> +  BOOLEAN                     IsTrunked;
>> +  BOOLEAN                     CanMeasureTime;
>> +
>> +  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;
>> +  CanMeasureTime = FALSE;
>> +  if (Context->Flags & DL_FLAG_TIME) {
>> +    ZeroMem (&StartTime, sizeof (StartTime));
>> +    CanMeasureTime = !EFI_ERROR (gRT->GetTime (&StartTime, NULL));
>> +  }
>> +
>> +  do {
>> +    SHELL_FREE_NON_NULL (ResponseMessage.Headers);
>> +    ResponseMessage.HeaderCount = 0;
>> +    gResponseCallbackComplete = FALSE;
>> +    ResponseMessage.BodyLength = Context->BufferSize;
>> +
>> +    if (ShellGetExecutionBreakFlag ()) {
>> +      Status = EFI_ABORTED;
>> +      break;
>> +    }
>> +
>> +    if (!Context->ContentDownloaded && !Context->ResponseToken.Event) {
>> +      Status = gBS->CreateEvent (
>> +                      EVT_NOTIFY_SIGNAL,
>> +                      TPL_CALLBACK,
>> +                      ResponseCallback,
>> +                      Context,
>> +                      &Context->ResponseToken.Event
>> +                      );
>> +      ASSERT_EFI_ERROR (Status);
>> +    } else {
>> +      ResponseMessage.Data.Response = NULL;
>> +    }
>> +
>> +    if (EFI_ERROR (Status)) {
>> +      break;
>> +    }
>> +
>> +    Status = Context->Http->Response (Context->Http, &Context-
>>> ResponseToken);
>> +    if (EFI_ERROR (Status)) {
>> +      break;
>> +    }
>> +
>> +    Status = WaitForCompletion (Context, &gResponseCallbackComplete);
>> +    if (EFI_ERROR (Status) && ResponseMessage.HeaderCount) {
>> +      Status = EFI_SUCCESS;
>> +    }
>> +
>> +    if (EFI_ERROR (Status)) {
>> +      Context->Http->Cancel (Context->Http, &Context->ResponseToken);
>> +      break;
>> +    }
>> +
>> +    if (!Context->ContentDownloaded) {
>> +      if (NEED_REDIRECTION (ResponseData.StatusCode)) {
>> +        //
>> +        // 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) {
>> +            PRINT_HII (
>> +              STRING_TOKEN (STR_HTTP_ERR_STATUSCODE),
>> +              Context->ServerAddrAndProto,
>> +              L"Recursive HTTP server relocation",
>> +              Context->Uri
>> +              );
>> +          }
>> +        } else {
>> +          //
>> +          // Bad reply from the server. Server must specify the location.
>> +          // Indicate that resource was not found, and no body collected.
>> +          //
>> +          Status = EFI_NOT_FOUND;
>> +        }
>> +
>> +        Context->Http->Cancel (Context->Http, &Context->ResponseToken);
>> +        break;
>> +      }
>> +
>> +      //
>> +      // Init message-body parser by header information.
>> +      //
>> +      if (!MsgParser) {
>> +        Status = HttpInitMsgParser (
>> +                   ResponseMessage.Data.Request->Method,
>> +                   ResponseData.StatusCode,
>> +                   ResponseMessage.HeaderCount,
>> +                   ResponseMessage.Headers,
>> +                   ParseMsg,
>> +                   Context,
>> +                   &MsgParser
>> +                   );
>> +        if (EFI_ERROR (Status)) {
>> +          break;
>> +        }
>> +      }
>> +
>> +      //
>> +      // If it is a trunked message, rely on the parser.
>> +      //
>> +      Header = HttpFindHeader (
>> +                 ResponseMessage.HeaderCount,
>> +                 ResponseMessage.Headers,
>> +                 "Transfer-Encoding"
>> +                 );
>> +      IsTrunked = (Header && !AsciiStrCmp (Header->FieldValue, "chunked"));
>> +
>> +      HttpGetEntityLength (MsgParser, &Context->ContentLength);
>> +
>> +      if (ResponseData.StatusCode >= HTTP_STATUS_400_BAD_REQUEST
>> +       && (ResponseData.StatusCode !=
>> HTTP_STATUS_308_PERMANENT_REDIRECT))
>> +      {
>> +        //
>> +        // Server reported an error via Response code.
>> +        // Collect the body if any.
>> +        //
>> +        if (!gHttpError) {
>> +          gHttpError = TRUE;
>> +
>> +          Desc = ErrStatusDesc[ResponseData.StatusCode -
>> +                               HTTP_STATUS_400_BAD_REQUEST];
>> +          PRINT_HII (
>> +            STRING_TOKEN (STR_HTTP_ERR_STATUSCODE),
>> +            Context->ServerAddrAndProto,
>> +            Desc,
>> +            Context->Uri
>> +            );
>> +
>> +          //
>> +          // This gives an RFC HTTP error.
>> +          //
>> +          Context->Status = ShellStrToUintn (Desc);
>> +          Status = ENCODE_ERROR (Context->Status);
>> +        }
>> +      }
>> +    }
>> +
>> +    //
>> +    // 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);
>> +
>> +  if (Context->Status != REQ_NEED_REPEAT
>> +   && Status == EFI_SUCCESS
>> +   && CanMeasureTime)
>> +  {
>> +    if (!EFI_ERROR (gRT->GetTime (&EndTime, NULL))) {
>> +      ElapsedSeconds = EfiTimeToEpoch (&EndTime) - EfiTimeToEpoch
>> (&StartTime);
>> +      Print (
>> +        L",%a%Lus\n",
>> +        ElapsedSeconds ? " " : " < ",
>> +        ElapsedSeconds > 1 ? (UINT64)ElapsedSeconds : 1
>> +        );
>> +    }
>> +  }
>> +
>> +  SHELL_FREE_NON_NULL (MsgParser);
>> +  if (Context->ResponseToken.Event) {
>> +    gBS->CloseEvent (Context->ResponseToken.Event);
>> +    ZeroMem (&Context->ResponseToken, sizeof (Context->ResponseToken));
>> +  }
>> +
>> +  return Status;
>> +}
>> +
>> +/**
>> +  Worker function that downloads the data of a file from an HTTP server 
>> given
>> +  the path of the file and its size.
>> +
>> +  @param[in]   Context           A pointer to the HTTP download context.
>> +  @param[in]   ControllerHandle  The handle of the network interface 
>> controller
>> +  @param[in]   NicName           NIC name
>> +
>> +  @retval  EFI_SUCCESS           The file was downloaded.
>> +  @retval  EFI_OUT_OF_RESOURCES  A memory allocation failed.
>> +  #return  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 HTTP_DOWNLOAD_CONTEXT   *Context,
>> +  IN EFI_HANDLE              ControllerHandle,
>> +  IN CHAR16                  *NicName
>> +  )
>> +{
>> +  EFI_STATUS                 Status;
>> +  CHAR16                     *DownloadUrl;
>> +  UINTN                      UrlSize;
>> +  EFI_HANDLE                 HttpChildHandle;
>> +
>> +  ASSERT (Context);
>> +  if (Context == NULL) {
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  DownloadUrl = NULL;
>> +  HttpChildHandle = NULL;
>> +
>> +  Context->Buffer = AllocatePool (Context->BufferSize);
>> +  if (Context->Buffer == NULL) {
>> +    Status = EFI_OUT_OF_RESOURCES;
>> +    goto ON_EXIT;
>> +  }
>> +
>> +  //
>> +  // Open the 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)) {
>> +    PRINT_HII_APP (STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL),
>> mLocalFilePath);
>> +    goto ON_EXIT;
>> +  }
>> +
>> +  do {
>> +    SHELL_FREE_NON_NULL (DownloadUrl);
>> +
>> +    CLOSE_HTTP_HANDLE (ControllerHandle, HttpChildHandle);
>> +
>> +    Status = CreateServiceChildAndOpenProtocol (
>> +               ControllerHandle,
>> +               &gEfiHttpServiceBindingProtocolGuid,
>> +               &gEfiHttpProtocolGuid,
>> +               &HttpChildHandle,
>> +               (VOID**)&Context->Http
>> +               );
>> +
>> +    if (EFI_ERROR (Status)) {
>> +      PRINT_HII (STRING_TOKEN (STR_HTTP_ERR_OPEN_PROTOCOL), NicName,
>> Status);
>> +      goto ON_EXIT;
>> +    }
>> +
>> +    Status = Context->Http->Configure (Context->Http, &Context-
>>> HttpConfigData);
>> +    if (EFI_ERROR (Status)) {
>> +      PRINT_HII (STRING_TOKEN (STR_HTTP_ERR_CONFIGURE), NicName,
>> Status);
>> +      goto ON_EXIT;
>> +    }
>> +
>> +    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));
>> +
>> +    PRINT_HII (STRING_TOKEN (STR_HTTP_DOWNLOADING), DownloadUrl);
>> +
>> +    Status = SendRequest (Context, DownloadUrl);
>> +    if (Status) {
>> +      goto ON_EXIT;
>> +    }
>> +
>> +    Status = GetResponse (Context, DownloadUrl);
>> +
>> +    if (Status) {
>> +      goto ON_EXIT;
>> +    }
>> +
>> +  } while (Context->Status == REQ_NEED_REPEAT);
>> +
>> +  if (Context->Status) {
>> +    Status = ENCODE_ERROR (Context->Status);
>> +  }
>> +
>> +ON_EXIT:
>> +  //
>> +  // Close the file.
>> +  //
>> +  if (mFileHandle != NULL) {
>> +    if (EFI_ERROR (Status) && !(Context->Flags & DL_FLAG_KEEP_BAD)) {
>> +      ShellDeleteFile (&mFileHandle);
>> +    } else {
>> +      ShellCloseFile (&mFileHandle);
>> +    }
>> +  }
>> +
>> +  SHELL_FREE_NON_NULL (DownloadUrl);
>> +  SHELL_FREE_NON_NULL (Context->Buffer);
>> +
>> +  CLOSE_HTTP_HANDLE (ControllerHandle, HttpChildHandle);
>> +
>> +  return Status;
>> +}
>> +
>> +/**
>> +  Retrive HII package list from ImageHandle and publish to HII database.
>> +
>> +  @param[in] ImageHandle            The image handle of the process.
>> +
>> +  @retval HII handle.
>> +**/
>> +EFI_HII_HANDLE
>> +InitializeHiiPackage (
>> +  IN 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/HttpApp.c
>> b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c
>> new file mode 100644
>> index 000000000000..a7d2c27191a2
>> --- /dev/null
>> +++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c
>> @@ -0,0 +1,61 @@
>> +/** @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;
>> +  SHELL_STATUS                ShellStatus;
>> +
>> +  mHttpHiiHandle = InitializeHiiPackage (ImageHandle);
>> +  if (mHttpHiiHandle == NULL) {
>> +    return EFI_ABORTED;
>> +  }
>> +
>> +  Status = EFI_SUCCESS;
>> +
>> +  ShellStatus = RunHttp (ImageHandle, SystemTable);
>> +
>> +  HiiRemovePackages (mHttpHiiHandle);
>> +
>> +  if (Status != SHELL_SUCCESS) {
>> +    Status = ENCODE_ERROR (ShellStatus);
>> +  }
>> +
>> +  return Status;
>> +}
>> diff --git
>> a/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.c
>> b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.c
>> new file mode 100644
>> index 000000000000..7f59cc74d2a7
>> --- /dev/null
>> +++
>> b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.c
>> @@ -0,0 +1,137 @@
>> +/** @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/Http.uni
>> b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni
>> new file mode 100644
>> index 000000000000..00cf05deeb5c
>> --- /dev/null
>> +++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni
>> @@ -0,0 +1,117 @@
>> +// /**
>> +//
>> +// (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>
>> +// Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved. <BR>
>> +// Copyright (c) 2020, Broadcom. All rights reserved.<BR>
>> +// SPDX-License-Identifier: BSD-2-Clause-Patent
>> +//
>> +// Module Name:
>> +//
>> +// Http.uni
>> +//
>> +// Abstract:
>> +//
>> +// String definitions for UEFI Shell HTTP command
>> +//
>> +//
>> +// **/
>> +
>> +/=#
>> +
>> +#langdef   en-US "english"
>> +
>> +#string STR_GEN_TOO_MANY           #language en-US "%H%s%N: Too many
>> arguments. Try help http.\r\n"
>> +#string STR_GEN_TOO_FEW            #language en-US "%H%s%N: Too few
>> arguments. Try help http.\r\n"
>> +#string STR_GEN_PARAM_INV          #language en-US "%H%s%N: Invalid
>> argument - '%H%s%N'. Try help http.\r\n"
>> +#string STR_GEN_PROBLEM            #language en-US "%H%s%N: Unknown flag -
>> '%H%s%N'. Try help http.\r\n"
>> +#string STR_GEN_FILE_OPEN_FAIL     #language en-US "%H%s%N: Cannot open
>> file - '%H%s%N'\r\n"
>> +#string STR_GEN_CRLF               #language en-US "\r\n"
>> +
>> +#string STR_HTTP_ERR_NO_NIC        #language en-US "No network interface
>> card found.\r\n"
>> +#string STR_HTTP_ERR_NIC_NAME      #language en-US "Failed to get the name
>> of the network interface card number %d - %r\r\n"
>> +#string STR_HTTP_ERR_OPEN_PROTOCOL #language en-US "Unable to open
>> HTTP protocol on '%H%s%N' - %r\r\n"
>> +#string STR_HTTP_ERR_CONFIGURE     #language en-US "Unable to configure
>> HTTP protocol on '%H%s%N' - %r\r\n"
>> +#string STR_HTTP_ERR_DOWNLOAD      #language en-US "Unable to download
>> the file '%H%s%N' on '%H%s%N' - %r\r\n"
>> +#string STR_HTTP_ERR_WRITE         #language en-US "Unable to write into 
>> file
>> '%H%s%N' - %r\r\n"
>> +#string STR_HTTP_ERR_NIC_NOT_FOUND #language en-US "Network Interface
>> Card '%H%s%N' not found.\r\n"
>> +#string STR_HTTP_ERR_STATUSCODE    #language en-US "\r'%H%s%N' reports
>> '%s' for '%H%s%N' \r\n"
>> +#string STR_HTTP_DOWNLOADING       #language en-US "Downloading
>> '%H%s%N'\r\n"
>> +
>> +#string STR_GET_HELP_HTTP          #language en-US ""
>> +".TH http 0 "Download a file from HTTP server."\r\n"
>> +".SH NAME\r\n"
>> +"Download a file from HTTP server.\r\n"
>> +".SH SYNOPSIS\r\n"
>> +" \r\n"
>> +"HTTP [-i interface] [-l port] [-t timeout] [-s size] [-m] [-k]\r\n"
>> +"      <URL> [localfilepath]\r\n"
>> +".SH OPTIONS\r\n"
>> +" \r\n"
>> +"  -i interface     - Specifies an adapter name, i.e., eth0.\r\n"
>> +"  -k                 Keep the downloaded file even if there was an 
>> error.\r\n"
>> +"                     If this parameter is not used, the file will be 
>> deleted.\r\n"
>> +"  -l port          - Specifies the local port number. Default value is 
>> 0\r\n"
>> +"                     and the port number is automatically assigned.\r\n"
>> +"  -m                 Measure and report download time (in seconds). \r\n"
>> +"  -s size            The size of the download buffer for a chunk, in 
>> bytes.\r\n"
>> +"                     Default is 32K. Note that larger buffer does not 
>> imply\r\n"
>> +"                     better speed.\r\n"
>> +"  -t timeout       - The number of seconds to wait for completion of\r\n"
>> +"                     requests and responses. Default is 0 which is 
>> 'automatic'.\r\n"
>> +"  %HURL%N\r\n"
>> +"  Two types of providing of URLs are supported:\r\n"
>> +"    1. tftp-like, where host and http_uri are separate parameters\r\n"
>> +"       (example: host /host_uri), and\r\n\"
>> +"    2. wget-like, where host and host_uri is one parameter.\r\n"
>> +"       (example: host/host_uri)\r\n"
>> +"\r\n"
>> +"    host             - Specifies HTTP Server address.\r\n
>> +                        Can be either IPv4 address or 'http (or 
>> https)://addr'\r\n
>> +                        Can use addresses resolvable by DNS as well. \r\n
>> +                        Port can be specified after ':' if needed. \r\n
>> +                        By default port 80 is used.\r\n"
>> +"    http_uri         - HTTP server URI to download the file.\r\n"
>> +"\r\n"
>> +"  localfilepath    - Local destination file path.\r\n"
>> +".SH DESCRIPTION\r\n"
>> +" \r\n"
>> +"NOTES:\r\n"
>> +"  1. The HTTP command allows geting of the file specified by its 
>> 'http_uri'\r\n"
>> +"     path from the HTTP server specified by its 'host' IPv4 address. If 
>> the\r\n"
>> +"     optional 'localfilepath' parameter is provided, the downloaded file 
>> is\r\n"
>> +"     stored locally using the provided file path. If the local file path 
>> is\r\n"
>> +"     not specified, the file is stored in the current directory using the 
>> file\r\n"
>> +"     server's name.\r\n"
>> +"  2. Before using the HTTP command, the network interface intended to
>> be\r\n"
>> +"     used to retrieve the file must be configured. This configuration may 
>> be\r\n"
>> +"     done by means of the 'ifconfig' command.\r\n"
>> +"  3. If a network interface is defined with the '-i' option then only 
>> this\r\n"
>> +"     interface will be used to retrieve the remote file. Otherwise, all
>> network\r\n"
>> +"     interfaces are tried in the order they have been discovered during 
>> the\r\n"
>> +"     DXE phase.\r\n"
>> +".SH EXAMPLES\r\n"
>> +" \r\n"
>> +"EXAMPLES:\r\n"
>> +"  * To get the file "dir1/file1.dat" from the HTTP server 192.168.1.1, 
>> port 8080,
>> and\r\n"
>> +"    store it as file2.dat in the current directory (use tftp-like URL 
>> format) :\r\n"
>> +"    fs0:\> http 192.168.1.1:8080 dir1/file1.dat file2.dat\r\n"
>> +"  * To get the file /image.bin via HTTPS from server 192.168.1.1 at port 
>> 443
>> \r\n"
>> +"    (default HTTPS port), and store it in the current directory: \r\n"
>> +"    fs0:\> http https://192.168.1.1 image.bin\r\n"
>> +"    To get an index file from http://google.com and place it into the \r\n"
>> +"    current directory:\r\n"
>> +"    fs0:\> http google.com index.html\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"
>> +"  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, and -k parameter is on command 
>> line,
>> +"                            the file wil be saved either as localfilepath 
>> filename,\r\n"
>> +"                            or as an URI name in the current 
>> directory.\r\n"
>> +"                            If '/' is at the end of the URL, and no 
>> locafilepath filename\r\n"
>> +"                            is given on the command line, the file will be 
>> retrieved as\r\n"
>> +"                            index.html.\r\n"
>> --
>> 2.28.0.394.ge197136389
> 
> 
> 
> 
> 
> 



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#65731): https://edk2.groups.io/g/devel/message/65731
Mute This Topic: https://groups.io/mt/77066501/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to