From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-ed1-f49.google.com (mail-ed1-f49.google.com [209.85.208.49]) by mx.groups.io with SMTP id smtpd.web10.3012.1601397816088378459 for ; Tue, 29 Sep 2020 09:43:37 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@broadcom.com header.s=google header.b=RWoDqppX; spf=permerror, err=parse error for token &{10 18 %{i}._ip.%{h}._ehlo.%{d}._spf.vali.email}: invalid domain name (domain: broadcom.com, ip: 209.85.208.49, mailfrom: vladimir.olovyannikov@broadcom.com) Received: by mail-ed1-f49.google.com with SMTP id j2so7050552eds.9 for ; Tue, 29 Sep 2020 09:43:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; h=from:mime-version:thread-index:date:message-id:subject:to:cc; bh=R7KpiF+/XUeRhvgPK+Q6/nhDbzmRO2mFO6OJSxeTL9E=; b=RWoDqppXYwNYedef0OwiMjKHcFPEUJVp3lGiVaeJea0NCQMVUKpCik9LeTia9z/LFY +cz4INjLRMUmepI/CyLzglkfsDSrTfR9CEPMZjxXQVxCQFy7B0xjCetvqOxcNC202+1u bEBJyZWqdcg7lhYDKdcehp0JpkDan4k8AWI+M= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:mime-version:thread-index:date:message-id :subject:to:cc; bh=R7KpiF+/XUeRhvgPK+Q6/nhDbzmRO2mFO6OJSxeTL9E=; b=trFUfqbH++wUYTcr9ipxgTHSrTqiyzh5uWVwwolE5Ic22uF4oefGFHQHmrsp8j4NZA RWNmtOko/POgGKuqukNbCDfs1/7PGvNKcLcwF32BGd8n2L5r0pVpQBCFMl06Hc5BbEOo +VEf9ex7+H/mstVgIKATfsgXldzKJyaTHy3/V+cjGHFvtcQKqDfit5QtvFnUEHncvcZm 8MZ/x3jbVLwRiJ4eqFCa2udM1yky4W+Sn5Sub0QmGPmCxv11KPYcd77ccSlyXe1GXJN8 074LRGBIFql6Al138PcY/SnkRooOOW4XhnLv11svjG6ktNr5cCalI+qmG48DTyziwzHZ GSsA== X-Gm-Message-State: AOAM532ChPNviN1CYPuXaj9i9KA+T9bg3Ixdq8GMcPPsGhsjlLgd1OKf MaE8asvqgWkCnJXP/KtYMfzTRG3D28I8WqPAjkagfQ== X-Google-Smtp-Source: ABdhPJzJHP9VI7dfnIrmlGUFMyWGjIy1CEWPkerYCpGNn5h1Er8YAOtz0nQkX3V6bCfoTKIwKK+09VeQVc2DFoaxPJo= X-Received: by 2002:a50:eb92:: with SMTP id y18mr4136038edr.373.1601397813745; Tue, 29 Sep 2020 09:43:33 -0700 (PDT) From: "Vladimir Olovyannikov" MIME-Version: 1.0 X-Mailer: Microsoft Outlook 16.0 Thread-Index: AdaWfqpnhcwiZi0wQpOqjdlDdqdLmg== Date: Tue, 29 Sep 2020 09:43:31 -0700 Message-ID: Subject: Re: [PATCH v13 1/1] ShellPkg/DynamicCommand: add HttpDynamicCommand To: "Gao, Zhichao" , devel@edk2.groups.io Cc: Samer El-Haj-Mahmoud , Laszlo Ersek , Maciej Rabeda , "Wu, Jiaxin" , "Fu, Siyuan" , "Ni, Ray" , Nd , gaoliming@byosoft.com.cn X-Groupsio-MsgNum: 65730 Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-256; boundary="000000000000e2aa6d05b0767b32" --000000000000e2aa6d05b0767b32 Content-Type: text/plain; charset="UTF-8" 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 > Sent: Monday, September 28, 2020 7:29 PM > To: Vladimir Olovyannikov ; > mailto:devel@edk2.groups.io > Cc: Samer El-Haj-Mahmoud ; Laszlo > Ersek ; Maciej Rabeda > ; Wu, Jiaxin ; Fu, > Siyuan ; Ni, Ray ; Liming Gao > ; Nd > Subject: RE: [PATCH v13 1/1] ShellPkg/DynamicCommand: add > HttpDynamicCommand > > Hi, > > I have checked in openCI and it is passed. > > Reviewed-by: Zhichao Gao > > Hi Laszlo, > > Do you have a plan to test this patch? > > Thanks, > Zhichao > > > -----Original Message----- > > From: Vladimir Olovyannikov > > Sent: Friday, September 25, 2020 4:41 AM > > To: mailto:devel@edk2.groups.io > > Cc: Vladimir Olovyannikov ; > Samer El- > > Haj-Mahmoud ; Laszlo Ersek > > ; Gao, Zhichao ; Maciej > Rabeda > > ; Wu, Jiaxin ; Fu, > Siyuan > > ; Ni, Ray ; Liming Gao > > ; Nd > > 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 > > > Cc: Samer El-Haj-Mahmoud > > Cc: Laszlo Ersek > > Cc: Zhichao Gao > > Cc: Maciej Rabeda > > Cc: Jiaxin Wu > > Cc: Siyuan Fu > > Cc: Ray Ni > > Cc: Liming Gao > > Cc: Nd > > --- > > 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 { > > + > > + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE > > + } > > + ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf > > > ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf > { > > > > 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.
> > +# Copyright (c) 2015, ARM Ltd. All rights reserved.
> > +# Copyright (c) 2020, Broadcom. All rights reserved.
> > +# > > +# 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.
> > +# Copyright (c) 2015, ARM Ltd. All rights reserved.
> > +# Copyright (c) 2020, Broadcom. All rights reserved.
> > +# > > +# 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.
> > + Copyright (c) 2015, ARM Ltd. All rights reserved.
> > + Copyright (c) 2020, Broadcom. All rights reserved.
> > + > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#ifndef _HTTP_H_ > > +#define _HTTP_H_ > > + > > +#include > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > +#include > > +#include > > + > > +#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.
> > + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
> > + (C) Copyright 2015 Hewlett Packard Enterprise Development LP
> > + Copyright (c) 2020, Broadcom. All rights reserved.
> > + > > + 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.
> > + Copyright (c) 2015, ARM Ltd. All rights reserved.
> > + Copyright (c) 2020, Broadcom. All rights reserved.
> > + > > + 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.
> > + Copyright (c) 2015, ARM Ltd. All rights reserved.
> > + Copyright (c) 2020, Broadcom. All rights reserved.
> > + > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > +#include > > +#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
> > +// Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
> > +// Copyright (c) 2020, Broadcom. All rights reserved.
> > +// 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" > > +" [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 --000000000000e2aa6d05b0767b32 Content-Type: application/pkcs7-signature; name="smime.p7s" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="smime.p7s" Content-Description: S/MIME Cryptographic Signature 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 CEeHLI4vWrczctSrj6Zfz8gkq/X5+VuLhz/qPpzbO0njI0wGXVzERHi75LgYNh6/3Nm0DdoHTwEq ClanLF/XPVk3/d8bR+y/AgMBAAGjggHZMIIB1TAOBgNVHQ8BAf8EBAMCBaAwgZ4GCCsGAQUFBwEB BIGRMIGOME0GCCsGAQUFBzAChkFodHRwOi8vc2VjdXJlLmdsb2JhbHNpZ24uY29tL2NhY2VydC9n c3BlcnNvbmFsc2lnbjJzaGEyZzNvY3NwLmNydDA9BggrBgEFBQcwAYYxaHR0cDovL29jc3AyLmds b2JhbHNpZ24uY29tL2dzcGVyc29uYWxzaWduMnNoYTJnMzBNBgNVHSAERjBEMEIGCisGAQQBoDIB KAowNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xvYmFsc2lnbi5jb20vcmVwb3NpdG9yeS8w CQYDVR0TBAIwADBEBgNVHR8EPTA7MDmgN6A1hjNodHRwOi8vY3JsLmdsb2JhbHNpZ24uY29tL2dz cGVyc29uYWxzaWduMnNoYTJnMy5jcmwwLQYDVR0RBCYwJIEidmxhZGltaXIub2xvdnlhbm5pa292 QGJyb2FkY29tLmNvbTATBgNVHSUEDDAKBggrBgEFBQcDBDAfBgNVHSMEGDAWgBRpcoJiMWeVRIV3 kYDEBDZJnXsLYTAdBgNVHQ4EFgQU+vsYKvV6xIXx4rzkdgiFVWkSRX4wDQYJKoZIhvcNAQELBQAD ggEBAD3mqkZw4/rXmlUqLemAHv+/v1dHzIihiPso0EMPCWPuLXJOB+V5/ycqiwvDX+NeqTRQScgR EsOdSN9GaElW/1gTGOKC65QdWNooQJ208QJzFvcDEC5bMtM9lgcbW/qzJkvCSz8RqxfweRm2bW9b c0RM78alM55SpavIo4Qfp2qn5uAFjYebPMgzXaJAUSkRezr+PQeN5padF72wbi6/kkCclyP1cQ9D 5MSDVvTKmRr+2pf0Gdoqc0SmH5BjdtTboujwk2/GyLJGD0CkqIn0QowF/Jn/uoIcHVs8dY44ZuSt cSE8fXhVGVKi9VWuEUBjNjG6JikByuL4u+7DsEYhdpoxggJvMIICawIBATBtMF0xCzAJBgNVBAYT AkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTMwMQYDVQQDEypHbG9iYWxTaWduIFBlcnNv bmFsU2lnbiAyIENBIC0gU0hBMjU2IC0gRzMCDAcNwm8IGGqjztPrkjANBglghkgBZQMEAgEFAKCB 1DAvBgkqhkiG9w0BCQQxIgQgBAas1S1pauio+1ZLUdyagVmYmSMROoF53NIYm41n4FQwGAYJKoZI hvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjAwOTI5MTY0MzM0WjBpBgkqhkiG 9w0BCQ8xXDBaMAsGCWCGSAFlAwQBKjALBglghkgBZQMEARYwCwYJYIZIAWUDBAECMAoGCCqGSIb3 DQMHMAsGCSqGSIb3DQEBCjALBgkqhkiG9w0BAQcwCwYJYIZIAWUDBAIBMA0GCSqGSIb3DQEBAQUA BIIBABO1W3nSNK8knBfks7VFUpAyiOJPs9P32DQOvbJjL4HI5f/ilhrSFk7fRtOh6VHE834mn+Y3 RC2rwL+GGLKUMGVC6L5xpUdy8sYOD1m9POE5j+mBF/zQB0XUnkU9v0rXQHJn9jwTvJuZeEqzblgZ n3aWn6HJf1+KVf6ZwUM2mUz/zTEH6qzZHzj4Enx4zLk8HNHy8box/SxXb+Gi47ghJ2biJcDwQLuG SRNJEQQUhZGoTyj3tY0+Cz8N+wHeaTjwe821mAuNOC65dUN8UjazXNXdl7vE8pD5qOC+n1zNoPhp 7uECcxlCbrDe8taWCcBzAb4DxlDsGdhrQCwxmLxwHvw= --000000000000e2aa6d05b0767b32--