From: "Vladimir Olovyannikov" <vladimir.olovyannikov@broadcom.com>
To: "Gao, Zhichao" <zhichao.gao@intel.com>, devel@edk2.groups.io
Cc: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>,
Laszlo Ersek <lersek@redhat.com>,
Maciej Rabeda <maciej.rabeda@linux.intel.com>,
"Wu, Jiaxin" <jiaxin.wu@intel.com>,
"Fu, Siyuan" <siyuan.fu@intel.com>, "Ni, Ray" <ray.ni@intel.com>,
Nd <nd@arm.com>,
gaoliming@byosoft.com.cn
Subject: Re: [PATCH v13 1/1] ShellPkg/DynamicCommand: add HttpDynamicCommand
Date: Tue, 29 Sep 2020 09:43:31 -0700 [thread overview]
Message-ID: <c71336d271a32eb555427963a680f356@mail.gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 91335 bytes --]
Hi Zhichao,
Thank you for review.
There is another commit waiting for review, which is related to Http, but
it is not related to ShellPkg:
https://edk2.groups.io/g/devel/message/64765
If one has a server which replies with Content-type: HTML, but does not
send the Content-Length field,
this confuses HttpMessageParser as it sets Content-Length header to 0, and
causes it to spin forever not incrementing the body start address.
The patch above fixes the bug.
I am not sure who this should be addressed to. I haven't seen a response
since Aug 28th when I sent the patch.
The issue is in DxeHttpLib.
Thank you,
Vladimir
> -----Original Message-----
> From: Gao, Zhichao <mailto:zhichao.gao@intel.com>
> Sent: Monday, September 28, 2020 7:29 PM
> To: Vladimir Olovyannikov <mailto:vladimir.olovyannikov@broadcom.com>;
> mailto:devel@edk2.groups.io
> Cc: Samer El-Haj-Mahmoud <mailto:Samer.El-Haj-Mahmoud@arm.com>; Laszlo
> Ersek <mailto:lersek@redhat.com>; Maciej Rabeda
> <mailto:maciej.rabeda@linux.intel.com>; Wu, Jiaxin
<mailto:jiaxin.wu@intel.com>; Fu,
> Siyuan <mailto:siyuan.fu@intel.com>; Ni, Ray <mailto:ray.ni@intel.com>;
Liming Gao
> <mailto:liming.gao@intel.com>; Nd <mailto:nd@arm.com>
> Subject: RE: [PATCH v13 1/1] ShellPkg/DynamicCommand: add
> HttpDynamicCommand
>
> Hi,
>
> I have checked in openCI and it is passed.
>
> Reviewed-by: Zhichao Gao <mailto:zhichao.gao@intel.com>
>
> Hi Laszlo,
>
> Do you have a plan to test this patch?
>
> Thanks,
> Zhichao
>
> > -----Original Message-----
> > From: Vladimir Olovyannikov
<mailto:vladimir.olovyannikov@broadcom.com>
> > Sent: Friday, September 25, 2020 4:41 AM
> > To: mailto:devel@edk2.groups.io
> > Cc: Vladimir Olovyannikov <mailto:vladimir.olovyannikov@broadcom.com>;
> Samer El-
> > Haj-Mahmoud <mailto:Samer.El-Haj-Mahmoud@arm.com>; Laszlo Ersek
> > <mailto:lersek@redhat.com>; Gao, Zhichao
<mailto:zhichao.gao@intel.com>; Maciej
> Rabeda
> > <mailto:maciej.rabeda@linux.intel.com>; Wu, Jiaxin
<mailto:jiaxin.wu@intel.com>; Fu,
> Siyuan
> > <mailto:siyuan.fu@intel.com>; Ni, Ray <mailto:ray.ni@intel.com>;
Liming Gao
> > <mailto:liming.gao@intel.com>; Nd <mailto:nd@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
> <mailto:vladimir.olovyannikov@broadcom.com>
> > Cc: Samer El-Haj-Mahmoud <mailto:Samer.El-Haj-Mahmoud@arm.com>
> > Cc: Laszlo Ersek <mailto:lersek@redhat.com>
> > Cc: Zhichao Gao <mailto:zhichao.gao@intel.com>
> > Cc: Maciej Rabeda <mailto:maciej.rabeda@linux.intel.com>
> > Cc: Jiaxin Wu <mailto:jiaxin.wu@intel.com>
> > Cc: Siyuan Fu <mailto:siyuan.fu@intel.com>
> > Cc: Ray Ni <mailto:ray.ni@intel.com>
> > Cc: Liming Gao <mailto:liming.gao@intel.com>
> > Cc: Nd <mailto:nd@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/HttpDynamicComma
> nd.in
> > f
> >
> b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma
> nd.in
> > f
> > new file mode 100644
> > index 000000000000..159cae214ccc
> > --- /dev/null
> > +++
> >
> b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma
> nd.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/HttpDynamicComma
> nd.c
> >
> b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma
> nd.c
> > new file mode 100644
> > index 000000000000..7f59cc74d2a7
> > --- /dev/null
> > +++
> >
> b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma
> nd.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
[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4193 bytes --]
next reply other threads:[~2020-09-29 16:43 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-09-29 16:43 Vladimir Olovyannikov [this message]
2020-09-30 1:04 ` [PATCH v13 1/1] ShellPkg/DynamicCommand: add HttpDynamicCommand Gao, Zhichao
2020-10-01 10:05 ` Laszlo Ersek
-- strict thread matches above, loose matches on Subject: below --
2020-09-24 20:40 [PATCH v13 0/1] " Vladimir Olovyannikov
2020-09-24 20:40 ` [PATCH v13 1/1] " Vladimir Olovyannikov
2020-09-29 2:29 ` Gao, Zhichao
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=c71336d271a32eb555427963a680f356@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