From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail.byosoft.com.cn (mail.byosoft.com.cn [58.240.74.243]) by mx.groups.io with SMTP id smtpd.web12.36821.1599465712454252503 for ; Mon, 07 Sep 2020 01:01:53 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=none, err=permanent DNS error (domain: byosoft.com.cn, ip: 58.240.74.243, mailfrom: gaoliming@byosoft.com.cn) Received: from DESKTOPS6D0PVI ([58.246.60.130]) (envelope-sender ) by 192.168.6.13 with ESMTP for ; Mon, 07 Sep 2020 16:01:07 +0800 X-WM-Sender: gaoliming@byosoft.com.cn X-WM-AuthFlag: YES X-WM-AuthUser: gaoliming@byosoft.com.cn From: "gaoliming" To: , , Cc: "'Samer El-Haj-Mahmoud'" , "'Laszlo Ersek'" , "'Maciej Rabeda'" , "'Wu, Jiaxin'" , "'Fu, Siyuan'" , "'Ni, Ray'" , "'Gao, Liming'" , "'Nd'" References: <20200830002847.12726-1-vladimir.olovyannikov@broadcom.com> <20200830002847.12726-3-vladimir.olovyannikov@broadcom.com> <83d2bd1699161581453f8f0ff2e3c676@mail.gmail.com> In-Reply-To: Subject: =?UTF-8?B?5Zue5aSNOiBbZWRrMi1kZXZlbF0gW1BBVENIIHY5IDEvMV0gU2hlbGxQa2cvRHluYW1pY0NvbW1hbmQ6IGFkZCBIdHRwRHluYW1pY0NvbW1hbmQ=?= Date: Mon, 7 Sep 2020 16:01:06 +0800 Message-ID: <002201d684ed$0acb2790$206176b0$@byosoft.com.cn> MIME-Version: 1.0 X-Mailer: Microsoft Outlook 16.0 Thread-Index: AQFA8MBsSI6oLUEhfBV/ukobnxwCYQIYgSA6AOs6lZcCaHA+jAMd+INOqkOnE4A= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Content-Language: zh-cn Zhichao: Dose ECC tool detect those issues? Now, ECC checker has been enabled in = open CI. The patch can be checked in PR request.=20 Thanks Liming > -----=E9=82=AE=E4=BB=B6=E5=8E=9F=E4=BB=B6----- > =E5=8F=91=E4=BB=B6=E4=BA=BA: bounce+27952+65078+4905953+8761045@groups.i= o > =E4=BB=A3=E8=A1=A8 Gao, Z= hichao > =E5=8F=91=E9=80=81=E6=97=B6=E9=97=B4: 2020=E5=B9=B49=E6=9C=887=E6=97=A5 = 15:30 > =E6=94=B6=E4=BB=B6=E4=BA=BA: devel@edk2.groups.io; vladimir.olovyannikov= @broadcom.com > =E6=8A=84=E9=80=81: Samer El-Haj-Mahmoud ;= Laszlo > Ersek ; Maciej Rabeda > ; Wu, Jiaxin ; Fu, > Siyuan ; Ni, Ray ; Gao, Liming > ; Nd > =E4=B8=BB=E9=A2=98: Re: [edk2-devel] [PATCH v9 1/1] ShellPkg/DynamicComm= and: add > HttpDynamicCommand >=20 > Hi Vladimmir, >=20 > There is no tools to check the coding style and the CCS spec. I check th= ru > personal review. Hope the check would added in the patch check in the > future. >=20 > Thanks, > Zhichao >=20 > > -----Original Message----- > > From: devel@edk2.groups.io On Behalf Of > Vladimir > > Olovyannikov via groups.io > > Sent: Wednesday, September 2, 2020 11:49 AM > > To: Gao, Zhichao ; devel@edk2.groups.io > > Cc: Samer El-Haj-Mahmoud ; Laszlo > Ersek > > ; Maciej Rabeda ; > Wu, > > Jiaxin ; Fu, Siyuan ; Ni, Ra= y > > ; Gao, Liming ; Nd > > > Subject: Re: [edk2-devel] [PATCH v9 1/1] ShellPkg/DynamicCommand: add > > HttpDynamicCommand > > > > Hi Zhichao, > > Thank you for the feedback. > > > > > -----Original Message----- > > > From: Gao, Zhichao > > > Sent: Tuesday, September 1, 2020 7:32 PM > > > To: devel@edk2.groups.io; vladimir.olovyannikov@broadcom.com > > > Cc: Samer El-Haj-Mahmoud ; Laszlo > > > Ersek ; Maciej Rabeda > > > ; Wu, Jiaxin ; F= u, > > > Siyuan ; Ni, Ray ; Gao, Limin= g > > > ; Nd > > > Subject: RE: [edk2-devel] [PATCH v9 1/1] ShellPkg/DynamicCommand: > add > > > HttpDynamicCommand > > > > > > There is no much change for the shell part VS V6. But there are stil= l > > some > > > coding issue. I already fixed it in my branch > > > https://github.com/ZhichaoGao/edk2/tree/push, only indent issue. > > Thank you for spotting these. > > Which tool do you use to find issues like this? > > I looked through the code and just overlooked this issue. > > > > > > Another issue is the EfiTimeToEpoch: > > > --- > > > UINT32 EpochDays; // Number of days elapsed since > EPOCH_JULIAN_DAY > > > UINT32 EpochSeconds; > > > > > > EpochDays =3D EfiGetEpochDays (Time); > > > --- > > > EfiGetEpochDays return UINTN and it would cause a warning (warning > would > > > be treated as error) under X64 build. Please fix it. > > OK. I actually took it exactly as it is in > > EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.c > > The very same issue exists there. Even though it builds fine with > > build -a X64 -b NOOPT -t GCC48 -p ShellPkg/ShellPkg.dsc -m > > > ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand. > inf > > I agree, it should have UINTN everywhere. > > Similar fix has to be done for > > EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.c in a later, separate > patch. > > > > > > Others are OK for me. > > > > > > Thanks, > > > Zhichao > > Thank you, > > Vladimir > > > > > > > -----Original Message----- > > > > From: devel@edk2.groups.io On Behalf Of > > > Vladimir > > > > Olovyannikov via groups.io > > > > Sent: Sunday, August 30, 2020 8:29 AM > > > > To: devel@edk2.groups.io > > > > Cc: Vladimir Olovyannikov ; > > > Samer El- > > > > Haj-Mahmoud ; Laszlo Ersek > > > > ; Gao, Zhichao ; Maciej > > > Rabeda > > > > ; Wu, Jiaxin ;= Fu, > > > Siyuan > > > > ; Ni, Ray ; Gao, Liming > > > > ; Nd > > > > Subject: [edk2-devel] [PATCH v9 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 ea= sy > > > > 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=3D2860 > > > > > > > > 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 | 58 + > > > > .../HttpDynamicCommand/HttpDynamicCommand.inf | 63 + > > > > .../DynamicCommand/HttpDynamicCommand/Http.h | 90 + > > > > ShellPkg/Include/Guid/ShellLibHiiGuid.h | 5 + > > > > .../DynamicCommand/HttpDynamicCommand/Http.c | 1830 > > > > +++++++++++++++++ > > > > .../HttpDynamicCommand/HttpApp.c | 61 + > > > > .../HttpDynamicCommand/HttpDynamicCommand.c | 137 ++ > > > > .../HttpDynamicCommand/Http.uni | 117 ++ > > > > 10 files changed, 2367 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 =3D {0xf3d301bb, 0xf4a5, > 0x45a8, > > {0xb0, 0xb7, > > > 0xfa, > > > > 0x99, 0x9c, 0x62, 0x37, 0xae}} > > > > gShellNetwork2HiiGuid =3D {0x174b2b5, 0xf505, 0x4b12, > > {0xaa, 0x60, > > > 0x59, > > > > 0xdf, 0xf8, 0xd6, 0xea, 0x37}} > > > > gShellTftpHiiGuid =3D {0x738a9314, 0x82c1, > 0x4592, > > {0x8f, 0xf7, 0xc1, > > > > 0xbd, 0xf1, 0xb2, 0x0e, 0xd4}} > > > > + gShellHttpHiiGuid =3D {0x390f84b3, 0x221c, 0x4d9e= , > > {0xb5, 0x06, > > > 0x6d, > > > > 0xb9, 0x42, 0x3e, 0x0a, 0x7e}} > > > > gShellBcfgHiiGuid =3D {0x5f5f605d, 0x1583, 0x4a2d= , > > {0xa6, 0xb2, 0xeb, > > > > 0x12, 0xda, 0xb4, 0xa2, 0xb6}} > > > > gShellAcpiViewHiiGuid =3D {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..d08d47fb37d5 > > > > --- /dev/null > > > > +++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf > > > > @@ -0,0 +1,58 @@ > > > > +## @file > > > > +# Provides Shell 'http' standalone application. > > > > +# > > > > +# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserv= ed. > >
> > > > +# 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 =3D 0x00010006 > > > > + BASE_NAME =3D http > > > > + FILE_GUID =3D > > 56B00FB7-91D2-869B-CE5C-26CD1A89C73C > > > > + MODULE_TYPE =3D UEFI_APPLICATION > > > > + VERSION_STRING =3D 1.0 > > > > + ENTRY_POINT =3D HttpAppInitialize > > > > +# > > > > +# This flag specifies whether HII resource section is generated = into > > PE > > > image. > > > > +# > > > > + UEFI_HII_RESOURCE_SECTION =3D TRUE > > > > + > > > > +[Sources.common] > > > > + Http.c > > > > + HttpApp.c > > > > + Http.h > > > > + Http.uni > > > > + > > > > +[Packages] > > > > + EmbeddedPkg/EmbeddedPkg.dec > > > > + MdeModulePkg/MdeModulePkg.dec > > > > + MdePkg/MdePkg.dec > > > > + NetworkPkg/NetworkPkg.dec > > > > + ShellPkg/ShellPkg.dec > > > > + > > > > +[LibraryClasses] > > > > + BaseLib > > > > + BaseMemoryLib > > > > + DebugLib > > > > + FileHandleLib > > > > + HiiLib > > > > + HttpLib > > > > + MemoryAllocationLib > > > > + NetLib > > > > + ShellLib > > > > + UefiApplicationEntryPoint > > > > + UefiBootServicesTableLib > > > > + UefiHiiServicesLib > > > > + UefiLib > > > > + UefiRuntimeServicesTableLib > > > > + > > > > +[Protocols] > > > > + gEfiHiiPackageListProtocolGuid ## CONSUMES > > > > + gEfiHttpProtocolGuid ## CONSUMES > > > > + gEfiHttpServiceBindingProtocolGuid ## CONSUMES > > > > + gEfiManagedNetworkServiceBindingProtocolGuid ## CONSUMES > > > > diff --git > > > > > > > > a/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma > > > nd.in > > > > f > > > > > > > > b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma > > > nd.in > > > > f > > > > new file mode 100644 > > > > index 000000000000..5d46ee2384d5 > > > > --- /dev/null > > > > +++ > > > > > > > > b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma > > > nd.in > > > > f > > > > @@ -0,0 +1,63 @@ > > > > +## @file > > > > +# Provides Shell 'http' dynamic command. > > > > +# > > > > +# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserv= ed. > >
> > > > +# 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 =3D 0x00010006 > > > > + BASE_NAME =3D httpDynamicCommand > > > > + FILE_GUID =3D > > 19618BCE-55AE-09C6-37E9-4CE04084C7A1 > > > > + MODULE_TYPE =3D DXE_DRIVER > > > > + VERSION_STRING =3D 1.0 > > > > + ENTRY_POINT =3D HttpCommandInitialize > > > > + UNLOAD_IMAGE =3D HttpUnload > > > > +# > > > > +# This flag specifies whether HII resource section is generated = into > > PE > > > image. > > > > +# > > > > + UEFI_HII_RESOURCE_SECTION =3D TRUE > > > > + > > > > +[Sources.common] > > > > + Http.c > > > > + HttpDynamicCommand.c > > > > + Http.h > > > > + Http.uni > > > > + > > > > +[Packages] > > > > + EmbeddedPkg/EmbeddedPkg.dec > > > > + MdePkg/MdePkg.dec > > > > + MdeModulePkg/MdeModulePkg.dec > > > > + NetworkPkg/NetworkPkg.dec > > > > + ShellPkg/ShellPkg.dec > > > > + > > > > +[LibraryClasses] > > > > + BaseLib > > > > + BaseMemoryLib > > > > + DebugLib > > > > + FileHandleLib > > > > + HiiLib > > > > + HttpLib > > > > + MemoryAllocationLib > > > > + NetLib > > > > + ShellLib > > > > + UefiBootServicesTableLib > > > > + UefiDriverEntryPoint > > > > + UefiHiiServicesLib > > > > + UefiLib > > > > + UefiRuntimeServicesTableLib > > > > + > > > > +[Protocols] > > > > + gEfiHiiPackageListProtocolGuid ## CONSUMES > > > > + gEfiHttpProtocolGuid ## CONSUMES > > > > + gEfiHttpServiceBindingProtocolGuid ## CONSUMES > > > > + gEfiManagedNetworkServiceBindingProtocolGuid ## CONSUMES > > > > + gEfiShellDynamicCommandProtocolGuid ## > PRODUCES > > > > + > > > > +[DEPEX] > > > > + TRUE > > > > diff --git a/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h > > > > b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h > > > > new file mode 100644 > > > > index 000000000000..c53479b823e7 > > > > --- /dev/null > > > > +++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h > > > > @@ -0,0 +1,90 @@ > > > > +/** @file > > > > + Header file for 'http' command functions. > > > > + > > > > + Copyright (c) 2010 - 2017, Intel Corporation. All rights reserv= ed. > >
> > > > + 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 fail= ed. > > > > + > > > > +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 > > > > + ); > > > > + > > > > +/** > > > > + Retrive HII package list from ImageHandle and publish to HII > > database. > > > > + > > > > + @param ImageHandle The image handle of the > process. > > > > + > > > > + @return HII handle. > > > > +**/ > > > > +EFI_HII_HANDLE > > > > +InitializeHiiPackage ( > > > > + EFI_HANDLE ImageHandle > > > > + ); > > > > +#endif // _HTTP_H_ > > > > diff --git a/ShellPkg/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, 0= xb2, > > 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..465706ab7757 > > > > --- /dev/null > > > > +++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c > > > > @@ -0,0 +1,1830 @@ > > > > +/** @file > > > > + The implementation for the 'http' Shell command. > > > > + > > > > + Copyright (c) 2015, ARM Ltd. All rights reserved.
> > > > + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserv= ed. > >
> > > > + (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 mess= age > > 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 1= 1 > > > > characters > > > > +// (2 // spaces, "Kb" and seven characters for the number of KByt= es). > > > > +#define HTTP_PROGRESS_MESSAGE_SIZE \ > > > > + ((sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) + 12) > > > > + > > > > +// > > > > +// Buffer size. Note that larger buffer does not mean better spee= d! > > > > +// > > > > +#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 >=3D HTTP_STATUS_300_MULTIPLE_CHOICES) \ > > > > + && (Code <=3D HTTP_STATUS_307_TEMPORARY_REDIRECT)) \ > > > > + || (Code =3D=3D HTTP_STATUS_308_PERMANENT_REDIRECT)) > > > > + > > > > +#define CLOSE_HTTP_HANDLE(ControllerHandle,HttpChildHandle) \ > > > > + do { \ > > > > + if (HttpChildHandle) { \ > > > > + CloseProtocolAndDestroyServiceChild ( \ > > > > + ControllerHandle, \ > > > > + &gEfiHttpServiceBindingProtocolGuid, \ > > > > + &gEfiHttpProtocolGuid, \ > > > > + HttpChildHandle \ > > > > + ); \ > > > > + HttpChildHandle =3D NULL; \ > > > > + } \ > > > > + } while (0) > > > > + > > > > +typedef enum { > > > > + HDR_HOST, > > > > + HDR_CONN, > > > > + HDR_AGENT, > > > > + HDR_MAX > > > > +} 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 updat= e 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"[ > > ]" > > > > + > > > > +#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) > > > > +#define SEC_PER_MONTH > ((UINTN) > > 2,592,000) > > > > +#define SEC_PER_YEAR > ((UINTN) > > 31,536,000) > > > > + > > > > +// 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) > > > > + > > > > +// String descriptions for server errors > > > > +STATIC CONST CHAR16 *ErrStatusDesc[] =3D > > > > +{ > > > > + 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[] =3D { > > > > + {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 =3D NULL; > > > > + > > > > +// Path of the local file, Unicode encoded > > > > +STATIC CONST CHAR16 *mLocalFilePath; > > > > + > > > > +STATIC BOOLEAN gRequestCallbackComplete =3D FALSE; > > > > +STATIC BOOLEAN gResponseCallbackComplete =3D FALSE; > > > > + > > > > +STATIC BOOLEAN gHttpError; > > > > + > > > > +EFI_HII_HANDLE mHttpHiiHandle; > > > > + > > > > +// Functions declarations > > > > +/** > > > > + Check and convert the UINT16 option values of the 'http' comman= d > > > > + > > > > + @param[in] ValueStr Value as an Unicode encoded string > > > > + @param[out] Value UINT16 value > > > > + > > > > + @return TRUE The value was returned. > > > > + @return FALSE A parsing error occured. > > > > +**/ > > > > +STATIC > > > > +BOOLEAN > > > > +StringToUint16 ( > > > > + IN CONST CHAR16 *ValueStr, > > > > + OUT UINT16 *Value > > > > + ); > > > > + > > > > +/** > > > > + Get the name of the NIC. > > > > + > > > > + @param[in] ControllerHandle The network physical device > handle. > > > > + @param[in] NicNumber The network physical device > number. > > > > + @param[out] NicName Address where to store the > NIC name. > > > > + The memory area has to be at > least > > > > + > > IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH > > > > + double byte wide. > > > > + > > > > + @return EFI_SUCCESS The name of the NIC was returned. > > > > + @return Others The creation of the child for the Managed > > > > + Network Service failed or the opening of > > > > + the Managed Network Protocol failed or > > > > + the operational parameters for the > > > > + Managed Network Protocol could not be > > > > + read. > > > > +**/ > > > > +STATIC > > > > +EFI_STATUS > > > > +GetNicName ( > > > > + IN EFI_HANDLE ControllerHandle, > > > > + IN UINTN NicNumber, > > > > + OUT CHAR16 *NicName > > > > + ); > > > > + > > > > +/** > > > > + Create a child for the service identified by its service bindin= g > > protocol > > > GUID > > > > + and get from the child the interface of the protocol identified= by > > its > > > GUID. > > > > + > > > > + @param[in] ControllerHandle Controller handle. > > > > + @param[in] ServiceBindingProtocolGuid Service binding > protocol > > GUID > > > of the > > > > + service to be > created. > > > > + @param[in] ProtocolGuid GUID of the > protocol to be > > open. > > > > + @param[out] ChildHandle Address where the > handler > > of the > > > > + created child is > returned. > > NULL is > > > > + returned in case > of error. > > > > + @param[out] Interface Address where a > pointer to > > the > > > > + protocol > interface is > > returned in > > > > + case of success. > > > > + > > > > + @return EFI_SUCCESS The child was created and the protocol > > opened. > > > > + @return Others Either the creation of the child or the > > opening > > > > + of the protocol failed. > > > > +**/ > > > > +STATIC > > > > +EFI_STATUS > > > > +CreateServiceChildAndOpenProtocol ( > > > > + IN EFI_HANDLE ControllerHandle, > > > > + IN EFI_GUID *ServiceBindingProtocolGuid, > > > > + IN EFI_GUID *ProtocolGuid, > > > > + OUT EFI_HANDLE *ChildHandle, > > > > + OUT VOID **Interface > > > > + ); > > > > + > > > > +/** > > > > + Close the protocol identified by its GUID on the child handle o= f > > the > > > service > > > > + identified by its service binding protocol GUID, then destroy t= he > > child > > > > + handle. > > > > + > > > > + @param[in] ControllerHandle Controller handle. > > > > + @param[in] ServiceBindingProtocolGuid Service binding protoco= l > > 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. > > > > +**/ > > > > +STATIC > > > > +EFI_STATUS > > > > +TrimSpaces ( > > > > + IN CHAR16 *String > > > > + ) > > > > +{ > > > > + CHAR16 *Str; > > > > + UINTN Len; > > > > + > > > > + ASSERT (String !=3D NULL); > > > > + > > > > + if (!String) { > > > > + return EFI_INVALID_PARAMETER; > > > > + } > > > > + > > > > + Str =3D String; > > > > + > > > > + // > > > > + // Remove any whitespace at the beginning of the Str. > > > > + // > > > > + while (*Str =3D=3D L' ' || *Str =3D=3D L'\t') { > > > > + Str++; > > > > + } > > > > + > > > > + // > > > > + // Remove any whitespace at the end of the Str. > > > > + // > > > > + do { > > > > + Len =3D StrLen (Str); > > > > + if (!Len || (Str[Len - 1] !=3D L' ' && Str[Len - 1] !=3D '\t'= )) { > > > > + break; > > > > + } > > > > + > > > > + Str[Len - 1] =3D 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. > > > > + */ > > > > +STATIC > > > > +VOID > > > > +EFIAPI > > > > +RequestCallback ( > > > > + IN EFI_EVENT Event, > > > > + IN VOID *Context > > > > +) > > > > +{ > > > > + gRequestCallbackComplete =3D TRUE; > > > > +} > > > > + > > > > +STATIC > > > > +VOID > > > > +EFIAPI > > > > +ResponseCallback ( > > > > + IN EFI_EVENT Event, > > > > + IN VOID *Context > > > > +) > > > > +{ > > > > + gResponseCallbackComplete =3D TRUE; > > > > +} > > > > + > > > > +/** > > > > + Calculate Epoch days > > > > + **/ > > > > +STATIC > > > > +UINTN > > > > +EfiGetEpochDays ( > > > > + IN EFI_TIME *Time > > > > + ) > > > > +{ > > > > + UINTN a; > > > > + UINTN y; > > > > + UINTN m; > > > > + UINTN JulianDate; // Absolute Julian Date representation of the > > supplied > > > Time > > > > + UINTN EpochDays; // Number of days elapsed since > > > EPOCH_JULIAN_DAY > > > > + > > > > + a =3D (14 - Time->Month) / 12 ; > > > > + y =3D Time->Year + 4800 - a; > > > > + m =3D Time->Month + (12 * a) - 3; > > > > + > > > > + JulianDate =3D Time->Day + ((153 * m + 2) / 5) + (365 * y) + (y= / 4) > > - > > > > + (y / 100) + (y / 400) - 32045; > > > > + > > > > + ASSERT (JulianDate >=3D EPOCH_JULIAN_DATE); > > > > + EpochDays =3D JulianDate - EPOCH_JULIAN_DATE; > > > > + > > > > + return EpochDays; > > > > +} > > > > +/** > > > > + Converts EFI_TIME to Epoch seconds > > > > + (elapsed since 1970 JANUARY 01, 00:00:00 UTC) > > > > + **/ > > > > +STATIC > > > > +UINT32 > > > > +EfiTimeToEpoch ( > > > > + IN EFI_TIME *Time > > > > + ) > > > > +{ > > > > + UINT32 EpochDays; // Number of days elapsed since > > > EPOCH_JULIAN_DAY > > > > + UINT32 EpochSeconds; > > > > + > > > > + EpochDays =3D EfiGetEpochDays (Time); > > > > + > > > > + EpochSeconds =3D (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). > > > > + > > > > + @return SHELL_SUCCESS The 'http' command > completed > > > successfully. > > > > + @return SHELL_ABORTED The Shell Library > initialization > > failed. > > > > + @return SHELL_INVALID_PARAMETER At least one of the > command's > > > > arguments is > > > > + not valid. > > > > + @return SHELL_OUT_OF_RESOURCES A memory allocation > failed. > > > > + @return SHELL_NOT_FOUND Network Interface Card > not found. > > > > + @return SHELL_UNSUPPORTED Command was valid, but > the server > > > > returned > > > > + a status code indicating > some > > error. > > > > + Examine the file > requested for > > error body. > > > > + > > > > +**/ > > > > +SHELL_STATUS > > > > +RunHttp ( > > > > + IN EFI_HANDLE ImageHandle, > > > > + IN EFI_SYSTEM_TABLE *SystemTable > > > > + ) > > > > +{ > > > > + EFI_STATUS Status; > > > > + LIST_ENTRY *CheckPackage; > > > > + 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 =3D NULL; > > > > + RemoteFilePath =3D NULL; > > > > + NicFound =3D FALSE; > > > > + Handles =3D NULL; > > > > + > > > > + // > > > > + // Initialize the Shell library (we must be in non-auto-init...= ) > > > > + // > > > > + ParamOffset =3D 0; > > > > + gHttpError =3D FALSE; > > > > + > > > > + Status =3D ShellInitialize (); > > > > + if (EFI_ERROR (Status)) { > > > > + ASSERT_EFI_ERROR (Status); > > > > + return SHELL_ABORTED; > > > > + } > > > > + > > > > + ZeroMem (&Context, sizeof (Context)); > > > > + > > > > + // > > > > + // Parse the command line. > > > > + // > > > > + Status =3D ShellCommandLineParse ( > > > > + ParamList, > > > > + &CheckPackage, > > > > + &ProblemParam, > > > > + TRUE > > > > + ); > > > > + if (EFI_ERROR (Status)) { > > > > + if ((Status =3D=3D EFI_VOLUME_CORRUPTED) > > > > + && (ProblemParam !=3D 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 =3D EFI_INVALID_PARAMETER; > > > > + > > > > + ParamCount =3D 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 =3D TRUE; > > > > + > > > > + Context.HttpConfigData.HttpVersion =3D HttpVersion11; > > > > + Context.HttpConfigData.AccessPoint.IPv4Node =3D &IPv4Node; > > > > + > > > > + // > > > > + // Get the host address (not necessarily IPv4 format) > > > > + // > > > > + ValueStr =3D ShellCommandLineGetRawValue (CheckPackage, 1); > > > > + if (!ValueStr) { > > > > + PRINT_HII_APP (STRING_TOKEN (STR_GEN_PARAM_INV), > ValueStr); > > > > + goto Error; > > > > + } else { > > > > + StartSize =3D 0; > > > > + TrimSpaces ((CHAR16 *)ValueStr); > > > > + if (!StrStr (ValueStr, L"://")) { > > > > + Context.ServerAddrAndProto =3D StrnCatGrow ( > > > > + > &Context.ServerAddrAndProto, > > > > + &StartSize, > > > > + DEFAULT_HTTP_PROTO, > > > > + StrLen > (DEFAULT_HTTP_PROTO) > > > > + ); > > > > + Context.ServerAddrAndProto =3D StrnCatGrow ( > > > > + > &Context.ServerAddrAndProto, > > > > + &StartSize, > > > > + L"://", > > > > + StrLen (L"://") > > > > + ); > > > > + VStr =3D (CHAR16 *)ValueStr; > > > > + } else { > > > > + VStr =3D StrStr (ValueStr, L"://") + StrLen (L"://"); > > > > + } > > > > + > > > > + for (Walker1 =3D VStr; *Walker1; Walker1++) { > > > > + if (*Walker1 =3D=3D L'/') { > > > > + break; > > > > + } > > > > + } > > > > + > > > > + if (*Walker1 =3D=3D L'/') { > > > > + ParamOffset =3D 1; > > > > + RemoteFilePath =3D Walker1; > > > > + } > > > > + > > > > + Context.ServerAddrAndProto =3D StrnCatGrow ( > > > > + > &Context.ServerAddrAndProto, > > > > + &StartSize, > > > > + ValueStr, > > > > + StrLen (ValueStr) - StrLen > > (Walker1) > > > > + ); > > > > + if (!Context.ServerAddrAndProto) { > > > > + Status =3D EFI_OUT_OF_RESOURCES; > > > > + goto Error; > > > > + } > > > > + } > > > > + > > > > + if (!RemoteFilePath) { > > > > + RemoteFilePath =3D ShellCommandLineGetRawValue > (CheckPackage, 2); > > > > + if (!RemoteFilePath) { > > > > + // If no path given, assume just "/" > > > > + RemoteFilePath =3D L"/"; > > > > + } > > > > + } > > > > + > > > > + TrimSpaces ((CHAR16 *)RemoteFilePath); > > > > + > > > > + if (ParamCount =3D=3D MAX_PARAM_COUNT - ParamOffset) { > > > > + mLocalFilePath =3D ShellCommandLineGetRawValue ( > > > > + CheckPackage, > > > > + MAX_PARAM_COUNT - 1 - ParamOffset > > > > + ); > > > > + } else { > > > > + Walker =3D RemoteFilePath + StrLen (RemoteFilePath); > > > > + while ((--Walker) >=3D RemoteFilePath) { > > > > + if ((*Walker =3D=3D L'\\') || > > > > + (*Walker =3D=3D L'/' ) ) { > > > > + break; > > > > + } > > > > + } > > > > + > > > > + mLocalFilePath =3D Walker + 1; > > > > + } > > > > + > > > > + if (!StrLen (mLocalFilePath)) { > > > > + mLocalFilePath =3D DEFAULT_HTML_FILE; > > > > + } > > > > + > > > > + InitialSize =3D 0; > > > > + Context.URI =3D StrnCatGrow ( > > > > + &Context.URI, > > > > + &InitialSize, > > > > + RemoteFilePath, > > > > + StrLen (RemoteFilePath) > > > > + ); > > > > + if (!Context.URI) { > > > > + Status =3D EFI_OUT_OF_RESOURCES; > > > > + goto Error; > > > > + } > > > > + > > > > + // > > > > + // Get the name of the Network Interface Card to be used if any= . > > > > + // > > > > + UserNicName =3D ShellCommandLineGetValue (CheckPackage, L"-i"); > > > > + > > > > + ValueStr =3D ShellCommandLineGetValue (CheckPackage, L"-l"); > > > > + if ((ValueStr !=3D NULL) > > > > + && (!StringToUint16 ( > > > > + ValueStr, > > > > + > &Context.HttpConfigData.AccessPoint.IPv4Node->LocalPort > > > > + ) > > > > + )) > > > > + { > > > > + goto Error; > > > > + } > > > > + > > > > + Context.BufferSize =3D DEFAULT_BUF_SIZE; > > > > + > > > > + ValueStr =3D ShellCommandLineGetValue (CheckPackage, L"-s"); > > > > + if (ValueStr !=3D NULL) { > > > > + Context.BufferSize =3D ShellStrToUintn (ValueStr); > > > > + if (!Context.BufferSize || Context.BufferSize > MAX_BUF_SIZE)= { > > > > + PRINT_HII_APP (STRING_TOKEN (STR_GEN_PARAM_INV), > ValueStr); > > > > + goto Error; > > > > + } > > > > + } > > > > + > > > > + ValueStr =3D ShellCommandLineGetValue (CheckPackage, L"-t"); > > > > + if (ValueStr !=3D NULL) { > > > > + Context.HttpConfigData.TimeOutMillisec =3D > (UINT32)ShellStrToUintn > > > > (ValueStr); > > > > + } > > > > + > > > > + // > > > > + // Locate all HTTP Service Binding protocols > > > > + // > > > > + Status =3D gBS->LocateHandleBuffer ( > > > > + ByProtocol, > > > > + > &gEfiManagedNetworkServiceBindingProtocolGuid, > > > > + NULL, > > > > + &HandleCount, > > > > + &Handles > > > > + ); > > > > + if (EFI_ERROR (Status) || (HandleCount =3D=3D 0)) { > > > > + PRINT_HII (STRING_TOKEN (STR_HTTP_ERR_NO_NIC), NULL); > > > > + if (!EFI_ERROR (Status)) { > > > > + Status =3D EFI_NOT_FOUND; > > > > + } > > > > + > > > > + goto Error; > > > > + } > > > > + > > > > + Status =3D EFI_NOT_FOUND; > > > > + > > > > + Context.Flags =3D 0; > > > > + if (ShellCommandLineGetFlag (CheckPackage, L"-m")) { > > > > + Context.Flags |=3D DL_FLAG_TIME; > > > > + } > > > > + > > > > + if (ShellCommandLineGetFlag (CheckPackage, L"-k")) { > > > > + Context.Flags |=3D DL_FLAG_KEEP_BAD; > > > > + } > > > > + > > > > + for (NicNumber =3D 0; > > > > + (NicNumber < HandleCount) && (Status !=3D EFI_SUCCESS); > > > > + NicNumber++) > > > > + { > > > > + ControllerHandle =3D Handles[NicNumber]; > > > > + > > > > + Status =3D GetNicName (ControllerHandle, NicNumber, NicName); > > > > + if (EFI_ERROR (Status)) { > > > > + PRINT_HII (STRING_TOKEN (STR_HTTP_ERR_NIC_NAME), > NicNumber, > > > > Status); > > > > + continue; > > > > + } > > > > + > > > > + if (UserNicName !=3D NULL) { > > > > + if (StrCmp (NicName, UserNicName) !=3D 0) { > > > > + Status =3D EFI_NOT_FOUND; > > > > + continue; > > > > + } > > > > + > > > > + NicFound =3D TRUE; > > > > + } > > > > + > > > > + Status =3D 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 =3D=3D EFI_ABORTED) { > > > > + goto Error; > > > > + } > > > > + } > > > > + > > > > + if (gHttpError) { > > > > + // > > > > + // This is not related to connection, so no need to repeat w= ith > > > > + // another interface. > > > > + // > > > > + break; > > > > + } > > > > + } > > > > + > > > > + if ((UserNicName !=3D 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' comman= d > > > > + > > > > + @param[in] ValueStr Value as an Unicode encoded string > > > > + @param[out] Value UINT16 value > > > > + > > > > + @return TRUE The value was returned. > > > > + @return FALSE A parsing error occured. > > > > +**/ > > > > +STATIC > > > > +BOOLEAN > > > > +StringToUint16 ( > > > > + IN CONST CHAR16 *ValueStr, > > > > + OUT UINT16 *Value > > > > + ) > > > > +{ > > > > + UINTN Val; > > > > + > > > > + Val =3D ShellStrToUintn (ValueStr); > > > > + if (Val > MAX_UINT16) { > > > > + PRINT_HII_APP (STRING_TOKEN (STR_GEN_PARAM_INV), > ValueStr); > > > > + return FALSE; > > > > + } > > > > + > > > > + *Value =3D (UINT16)Val; > > > > + return TRUE; > > > > +} > > > > + > > > > +/** > > > > + Get the name of the NIC. > > > > + > > > > + @param[in] ControllerHandle The network physical device > handle. > > > > + @param[in] NicNumber The network physical device > number. > > > > + @param[out] NicName Address where to store the > NIC name. > > > > + The memory area has to be at > least > > > > + > > IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH > > > > + double byte wide. > > > > + > > > > + @return EFI_SUCCESS The name of the NIC was returned. > > > > + @return Others The creation of the child for the Managed > > > > + Network Service failed or the opening of > > > > + the Managed Network Protocol failed or > > > > + the operational parameters for the > > > > + Managed Network Protocol could not be > > > > + read. > > > > +**/ > > > > +STATIC > > > > +EFI_STATUS > > > > +GetNicName ( > > > > + IN EFI_HANDLE ControllerHandle, > > > > + IN UINTN NicNumber, > > > > + OUT CHAR16 *NicName > > > > + ) > > > > +{ > > > > + EFI_STATUS Status; > > > > + EFI_HANDLE MnpHandle; > > > > + EFI_MANAGED_NETWORK_PROTOCOL *Mnp; > > > > + EFI_SIMPLE_NETWORK_MODE SnpMode; > > > > + > > > > + Status =3D CreateServiceChildAndOpenProtocol ( > > > > + ControllerHandle, > > > > + &gEfiManagedNetworkServiceBindingProtocolGuid, > > > > + &gEfiManagedNetworkProtocolGuid, > > > > + &MnpHandle, > > > > + (VOID**)&Mnp > > > > + ); > > > > + if (EFI_ERROR (Status)) { > > > > + goto Error; > > > > + } > > > > + > > > > + Status =3D Mnp->GetModeData (Mnp, NULL, &SnpMode); > > > > + if (EFI_ERROR (Status) && (Status !=3D EFI_NOT_STARTED)) { > > > > + goto Error; > > > > + } > > > > + > > > > + UnicodeSPrint ( > > > > + NicName, > > > > + IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH, > > > > + SnpMode.IfType =3D=3D NET_IFTYPE_ETHERNET ? L"eth%d" : > L"unk%d", > > > > + NicNumber > > > > + ); > > > > + > > > > + Status =3D EFI_SUCCESS; > > > > + > > > > +Error: > > > > + > > > > + if (MnpHandle !=3D NULL) { > > > > + CloseProtocolAndDestroyServiceChild ( > > > > + ControllerHandle, > > > > + &gEfiManagedNetworkServiceBindingProtocolGuid, > > > > + &gEfiManagedNetworkProtocolGuid, > > > > + MnpHandle > > > > + ); > > > > + } > > > > + > > > > + return Status; > > > > +} > > > > + > > > > +/** > > > > + Create a child for the service identified by its service bindin= g > > protocol > > > GUID > > > > + and get from the child the interface of the protocol identified= by > > its > > > GUID. > > > > + > > > > + @param[in] ControllerHandle Controller handle. > > > > + @param[in] ServiceBindingProtocolGuid Service binding > protocol > > GUID > > > of the > > > > + service to be > created. > > > > + @param[in] ProtocolGuid GUID of the > protocol to be > > open. > > > > + @param[out] ChildHandle Address where the > handler > > of the > > > > + created child is > returned. > > NULL is > > > > + returned in case > of error. > > > > + @param[out] Interface Address where a > pointer to > > the > > > > + protocol > interface is > > returned in > > > > + case of success. > > > > + > > > > + @return EFI_SUCCESS The child was created and the protocol > > opened. > > > > + @return Others Either the creation of the child or the > > opening > > > > + of the protocol failed. > > > > +**/ > > > > +STATIC > > > > +EFI_STATUS > > > > +CreateServiceChildAndOpenProtocol ( > > > > + IN EFI_HANDLE ControllerHandle, > > > > + IN EFI_GUID *ServiceBindingProtocolGuid, > > > > + IN EFI_GUID *ProtocolGuid, > > > > + OUT EFI_HANDLE *ChildHandle, > > > > + OUT VOID **Interface > > > > + ) > > > > +{ > > > > + EFI_STATUS Status; > > > > + > > > > + *ChildHandle =3D NULL; > > > > + Status =3D NetLibCreateServiceChild ( > > > > + ControllerHandle, > > > > + gImageHandle, > > > > + ServiceBindingProtocolGuid, > > > > + ChildHandle > > > > + ); > > > > + if (!EFI_ERROR (Status)) { > > > > + Status =3D gBS->OpenProtocol ( > > > > + *ChildHandle, > > > > + ProtocolGuid, > > > > + Interface, > > > > + gImageHandle, > > > > + ControllerHandle, > > > > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > > > > + ); > > > > + if (EFI_ERROR (Status)) { > > > > + NetLibDestroyServiceChild ( > > > > + ControllerHandle, > > > > + gImageHandle, > > > > + ServiceBindingProtocolGuid, > > > > + *ChildHandle > > > > + ); > > > > + *ChildHandle =3D NULL; > > > > + } > > > > + } > > > > + > > > > + return Status; > > > > +} > > > > + > > > > +/** > > > > + Close the protocol identified by its GUID on the child handle o= f > > the > > > service > > > > + identified by its service binding protocol GUID, then destroy t= he > > child > > > > + handle. > > > > + > > > > + @param[in] ControllerHandle Controller handle. > > > > + @param[in] ServiceBindingProtocolGuid Service binding protoco= l > > GUID > > > of the > > > > + service to be > destroyed. > > > > + @param[in] ProtocolGuid GUID of the protocol > to be > > closed. > > > > + @param[in] ChildHandle Handle of the child > to be > > destroyed. > > > > + > > > > +**/ > > > > +STATIC > > > > +VOID > > > > +CloseProtocolAndDestroyServiceChild ( > > > > + IN EFI_HANDLE ControllerHandle, > > > > + IN EFI_GUID *ServiceBindingProtocolGuid, > > > > + IN EFI_GUID *ProtocolGuid, > > > > + IN EFI_HANDLE ChildHandle > > > > + ) > > > > +{ > > > > + gBS->CloseProtocol ( > > > > + ChildHandle, > > > > + ProtocolGuid, > > > > + gImageHandle, > > > > + ControllerHandle > > > > + ); > > > > + > > > > + NetLibDestroyServiceChild ( > > > > + ControllerHandle, > > > > + gImageHandle, > > > > + ServiceBindingProtocolGuid, > > > > + ChildHandle > > > > + ); > > > > +} > > > > + > > > > +/** > > > > + Wait until operation completes. Completion is indicated by > > > > + setting of an appropriate variable. > > > > + > > > > + @param[in] Context A pointer to the HTTP > download > > context. > > > > + @param[in] CallBackComplete A pointer to the callback > > completion > > > > + variable set by the > callback. > > > > + > > > > + @return EFI_SUCCESS Callback signalled > completion. > > > > + @return EFI_TIMEOUT Timed out waiting for > completion. > > > > + @return Others Error waiting for > completion. > > > > +**/ > > > > +STATIC > > > > +EFI_STATUS > > > > +WaitForCompletion ( > > > > + IN HTTP_DOWNLOAD_CONTEXT *Context, > > > > + IN OUT BOOLEAN *CallBackComplete > > > > + ) > > > > +{ > > > > + EFI_STATUS Status; > > > > + EFI_EVENT WaitEvt; > > > > + > > > > + Status =3D EFI_SUCCESS; > > > > + > > > > + // Use a timer to measure timeout. Cannot use Stall here! > > > > + Status =3D gBS->CreateEvent ( > > > > + EVT_TIMER, > > > > + TPL_CALLBACK, > > > > + NULL, > > > > + NULL, > > > > + &WaitEvt > > > > + ); > > > > + ASSERT_EFI_ERROR (Status); > > > > + > > > > + if (!EFI_ERROR (Status)) { > > > > + Status =3D 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 =3D Context->Http->Poll (Context->Http); > > > > + if (!Context->ContentDownloaded > > > > + && CallBackComplete =3D=3D &gResponseCallbackComplete) > > > > + { > > > > + // > > > > + // An HTTP server may just send a response redirection head= er. > > > > + // 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 popula= ted, > > > > + // 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 =3D EFI_TIMEOUT; > > > > + } > > > > + > > > > + return Status; > > > > +} > > > > + > > > > +/** > > > > + Generate and send a request to the http server. > > > > + > > > > + @param[in] Context HTTP download context. > > > > + @param[in] DownloadUrl Fully qualified URL to be > > downloaded. > > > > + > > > > + @return EFI_SUCCESS Request has been sent > successfully. > > > > + @return EFI_INVALID_PARAMETER Invalid URL. > > > > + @return EFI_OUT_OF_RESOURCES Out of memory. > > > > + @return EFI_DEVICE_ERROR If HTTPS is used, this probably > > > > + means that TLS support either > was > > not > > > > + installed or not configured. > > > > + @return Others Error sending the request. > > > > +**/ > > > > + > > > > +STATIC > > > > +EFI_STATUS > > > > +SendRequest ( > > > > + IN HTTP_DOWNLOAD_CONTEXT *Context, > > > > + IN CHAR16 *DownloadUrl > > > > + ) > > > > +{ > > > > + EFI_HTTP_REQUEST_DATA RequestData; > > > > + EFI_HTTP_HEADER RequestHeader[HDR_MAX]; > > > > + 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[HDR_HOST].FieldName =3D "Host"; > > > > + RequestHeader[HDR_CONN].FieldName =3D "Connection"; > > > > + RequestHeader[HDR_AGENT].FieldName =3D "User-Agent"; > > > > + > > > > + Host =3D (CHAR16 *)Context->ServerAddrAndProto; > > > > + while (*Host !=3D CHAR_NULL && *Host !=3D L'/') { > > > > + Host++; > > > > + } > > > > + > > > > + if (*Host =3D=3D CHAR_NULL) { > > > > + return EFI_INVALID_PARAMETER; > > > > + } > > > > + > > > > + // > > > > + // Get the next slash > > > > + // > > > > + Host++; > > > > + // > > > > + // And now the host name > > > > + // > > > > + Host++; > > > > + > > > > + StringSize =3D StrLen (Host) + 1; > > > > + RequestHeader[HDR_HOST].FieldValue =3D AllocatePool (StringSi= ze); > > > > + if (!RequestHeader[HDR_HOST].FieldValue) { > > > > + return EFI_OUT_OF_RESOURCES; > > > > + } > > > > + > > > > + UnicodeStrToAsciiStrS ( > > > > + Host, > > > > + RequestHeader[HDR_HOST].FieldValue, > > > > + StringSize > > > > + ); > > > > + > > > > + RequestHeader[HDR_CONN].FieldValue =3D "close"; > > > > + RequestHeader[HDR_AGENT].FieldValue =3D USER_AGENT_HDR; > > > > + RequestMessage.HeaderCount =3D HDR_MAX; > > > > + > > > > + RequestData.Method =3D HttpMethodGet; > > > > + RequestData.Url =3D DownloadUrl; > > > > + > > > > + RequestMessage.Data.Request =3D &RequestData; > > > > + RequestMessage.Headers =3D RequestHeader; > > > > + RequestMessage.BodyLength =3D 0; > > > > + RequestMessage.Body =3D NULL; > > > > + Context->RequestToken.Event =3D NULL; > > > > + > > > > + // > > > > + // Completion callback event to be set when Request completes= . > > > > + // > > > > + Status =3D gBS->CreateEvent ( > > > > + EVT_NOTIFY_SIGNAL, > > > > + TPL_CALLBACK, > > > > + RequestCallback, > > > > + Context, > > > > + &Context->RequestToken.Event > > > > + ); > > > > + ASSERT_EFI_ERROR (Status); > > > > + > > > > + Context->RequestToken.Status =3D EFI_SUCCESS; > > > > + Context->RequestToken.Message =3D &RequestMessage; > > > > + gRequestCallbackComplete =3D FALSE; > > > > + Status =3D Context->Http->Request (Context->Http, &Context- > > > >RequestToken); > > > > + if (EFI_ERROR (Status)) { > > > > + goto Error; > > > > + } > > > > + > > > > + Status =3D WaitForCompletion (Context, > &gRequestCallbackComplete); > > > > + if (EFI_ERROR (Status)) { > > > > + Context->Http->Cancel (Context->Http, > &Context->RequestToken); > > > > + } > > > > + > > > > +Error: > > > > + SHELL_FREE_NON_NULL > (RequestHeader[HDR_HOST].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 =3D 0; > > > > + Step =3D 0; > > > > + > > > > + ShellSetFilePosition (mFileHandle, > Context->LastReportedNbOfBytes); > > > > + Status =3D 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 =3D=3D 0) { > > > > + ShellPrintEx (-1, -1, L"%s 0 Kb", HTTP_PROGR_FRAME); > > > > + } > > > > + > > > > + Context->ContentDownloaded +=3D DownloadLen; > > > > + NbOfKb =3D Context->ContentDownloaded >> 10; > > > > + > > > > + Progress[0] =3D L'\0'; > > > > + if (Context->ContentLength) { > > > > + LastStep =3D (Context->LastReportedNbOfBytes * > > > > HTTP_PROGRESS_SLIDER_STEPS) / > > > > + Context->ContentLength; > > > > + Step =3D (Context->ContentDownloaded * > > > HTTP_PROGRESS_SLIDER_STEPS) / > > > > + Context->ContentLength; > > > > + } > > > > + > > > > + Context->LastReportedNbOfBytes =3D Context->ContentDownloaded; > > > > + > > > > + if (Step <=3D LastStep) { > > > > + if (!Context->ContentLength) { > > > > + // > > > > + // Update downloaded size, there is no length info availabl= e. > > > > + // > > > > + 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 =3D StrCpyS (Progress, HTTP_PROGRESS_MESSAGE_SIZE, > > > > HTTP_PROGR_FRAME); > > > > + if (EFI_ERROR (Status)) { > > > > + return Status; > > > > + } > > > > + > > > > + for (Index =3D 1; Index < Step; Index++) { > > > > + Progress[Index] =3D L'=3D'; > > > > + } > > > > + > > > > + if (Step) { > > > > + Progress[Step] =3D L'>'; > > > > + } > > > > + > > > > + UnicodeSPrint ( > > > > + Progress + (sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) - 1, > > > > + sizeof (Progress) - sizeof (HTTP_PROGR_FRAME), > > > > + L" %7d Kb", > > > > + NbOfKb > > > > + ); > > > > + > > > > + > > > > + ShellPrintEx (-1, -1, L"%s", Progress); > > > > + > > > > + return EFI_SUCCESS; > > > > +} > > > > + > > > > +/** > > > > + Replace the original Host and URI with Host and URI returned by= the > > > > + HTTP server in 'Location' header (redirection). > > > > + > > > > + @param[in] Location A pointer to the 'Location' > string > > > > + provided by HTTP server. > > > > + @param[in] Context A pointer to HTTP download > context. > > > > + @param[in] DownloadUrl Fully qualified HTTP URL. > > > > + > > > > + @return EFI_SUCCESS Host and URI were > successfully set. > > > > + @return EFI_OUT_OF_RESOURCES Error setting Host or URI. > > > > +**/ > > > > + > > > > +STATIC > > > > +EFI_STATUS > > > > +SetHostURI ( > > > > + IN CHAR8 *Location, > > > > + IN 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 =3D NULL; > > > > + Url =3D NULL; > > > > + IsAbEmptyUrl =3D FALSE; > > > > + FirstStep =3D 0; > > > > + > > > > + StringSize =3D (AsciiStrSize (Location) * sizeof (CHAR16)); > > > > + Url =3D AllocateZeroPool (StringSize); > > > > + if (!Url) { > > > > + return EFI_OUT_OF_RESOURCES; > > > > + } > > > > + > > > > + Status =3D AsciiStrToUnicodeStrS ( > > > > + (CONST CHAR8 *)Location, > > > > + Url, > > > > + StringSize > > > > + ); > > > > + > > > > + if (EFI_ERROR (Status)) { > > > > + goto Error; > > > > + } > > > > + > > > > + // > > > > + // If an HTTP server redirects to the same location more than o= nce, > > > > + // then stop attempts and tell it is not reachable. > > > > + // > > > > + if (!StrCmp (Url, DownloadUrl)) { > > > > + Status =3D EFI_NO_MAPPING; > > > > + goto Error; > > > > + } > > > > + > > > > + if (AsciiStrLen (Location) > 2) { > > > > + // Some servers return 'Location: //server/resource' > > > > + IsAbEmptyUrl =3D (Location[0] =3D=3D '/') && (Location[1] =3D= = =3D '/'); > > > > + if (IsAbEmptyUrl) { > > > > + // Skip first "//" > > > > + Location +=3D 2; > > > > + FirstStep =3D 1; > > > > + } > > > > + } > > > > + > > > > + if (AsciiStrStr (Location, "://") || IsAbEmptyUrl) { > > > > + Idx =3D 0; > > > > + Walker =3D Location; > > > > + > > > > + for (Step =3D FirstStep; Step < 2; Step++) { > > > > + for (; *Walker !=3D '/' && *Walker !=3D '\0'; Walker++) { > > > > + Idx++; > > > > + } > > > > + > > > > + if (!Step) { > > > > + // > > > > + // Skip "//" > > > > + // > > > > + Idx +=3D 2; > > > > + Walker +=3D 2; > > > > + } > > > > + } > > > > + > > > > + Tmp =3D AllocateZeroPool (Idx + 1); > > > > + if (!Tmp) { > > > > + Status =3D EFI_OUT_OF_RESOURCES; > > > > + goto Error; > > > > + } > > > > + > > > > + CopyMem (Tmp, Location, Idx); > > > > + > > > > + // > > > > + // Location now points to URI > > > > + // > > > > + Location +=3D Idx; > > > > + StringSize =3D (Idx + 1) * sizeof (CHAR16); > > > > + > > > > + SHELL_FREE_NON_NULL (Context->ServerAddrAndProto); > > > > + > > > > + Temp =3D AllocateZeroPool (StringSize); > > > > + if (!Temp) { > > > > + Status =3D EFI_OUT_OF_RESOURCES; > > > > + goto Error; > > > > + } > > > > + > > > > + Status =3D AsciiStrToUnicodeStrS ( > > > > + (CONST CHAR8 *)Tmp, > > > > + Temp, > > > > + StringSize > > > > + ); > > > > + if (EFI_ERROR (Status)) { > > > > + SHELL_FREE_NON_NULL (Temp); > > > > + goto Error; > > > > + } > > > > + > > > > + Idx =3D 0; > > > > + if (IsAbEmptyUrl) { > > > > + Context->ServerAddrAndProto =3D StrnCatGrow ( > > > > + > &Context->ServerAddrAndProto, > > > > + &Idx, > > > > + L"http://", > > > > + StrLen (L"http://") > > > > + ); > > > > + } > > > > + > > > > + Context->ServerAddrAndProto =3D StrnCatGrow ( > > > > + > &Context->ServerAddrAndProto, > > > > + &Idx, > > > > + Temp, > > > > + StrLen (Temp) > > > > + ); > > > > + SHELL_FREE_NON_NULL (Temp); > > > > + if (!Context->ServerAddrAndProto) { > > > > + Status =3D EFI_OUT_OF_RESOURCES; > > > > + goto Error; > > > > + } > > > > + } > > > > + > > > > + SHELL_FREE_NON_NULL (Context->URI); > > > > + > > > > + StringSize =3D AsciiStrSize (Location) * sizeof (CHAR16); > > > > + Context->URI =3D AllocateZeroPool (StringSize); > > > > + if (!Context->URI) { > > > > + Status =3D EFI_OUT_OF_RESOURCES; > > > > + goto Error; > > > > + } > > > > + > > > > + // > > > > + // Now make changes to the URI part. > > > > + // > > > > + Status =3D AsciiStrToUnicodeStrS ( > > > > + (CONST CHAR8 *)Location, > > > > + Context->URI, > > > > + StringSize > > > > + ); > > > > +Error: > > > > + SHELL_FREE_NON_NULL (Tmp); > > > > + SHELL_FREE_NON_NULL (Url); > > > > + > > > > + return Status; > > > > +} > > > > + > > > > +/** > > > > + Message parser callback. > > > > + Save a portion of HTTP body. > > > > + > > > > + @param[in] EventType Type of event. Can be either > > > > + OnComplete or OnData. > > > > + @param[in] Data A pointer to the buffer with data. > > > > + @param[in] Length Data length of this portion. > > > > + @param[in] Context A pointer to the HTTP download > > context. > > > > + > > > > + @return EFI_SUCCESS The portion was processed > successfully. > > > > + @return Other Error returned by SavePortion. > > > > +**/ > > > > + > > > > +STATIC > > > > +EFI_STATUS > > > > +EFIAPI > > > > +ParseMsg ( > > > > + IN HTTP_BODY_PARSE_EVENT EventType, > > > > + IN CHAR8 *Data, > > > > + IN UINTN Length, > > > > + IN VOID *Context > > > > + ) > > > > +{ > > > > + if (!Data || (EventType =3D=3D BodyParseEventOnComplete) || !Co= ntext) > { > > > > + 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 s= end > > > > + the body as well. This body will be collected in the resultant > > file. > > > > + > > > > + @param[in] Context A pointer to the HTTP download > > context. > > > > + @param[in] DownloadedUrl A pointer to the fully qualified > URL > > to > > > download. > > > > + > > > > + @return EFI_SUCCESS Valid file. Body successfully > > collected. > > > > + @return EFI_HTTP_ERROR Response is a valid HTTP > response, but > > the > > > > + HTTP server > > > > + indicated an error (HTTP code >=3D > 400). > > > > + Response body MAY contain full > > > > + HTTP server response. > > > > + @return Others Error getting the reponse from the > > HTTP server. > > > > + Response body is not collected. > > > > +**/ > > > > +STATIC > > > > +EFI_STATUS > > > > +GetResponse ( > > > > + IN 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 =3D FALSE; > > > > + > > > > + ResponseMessage.Body =3D Context->Buffer; > > > > + Context->ResponseToken.Status =3D EFI_SUCCESS; > > > > + Context->ResponseToken.Message =3D &ResponseMessage; > > > > + Context->ContentLength =3D 0; > > > > + Context->Status =3D REQ_OK; > > > > + MsgParser =3D NULL; > > > > + ResponseData.StatusCode =3D HTTP_STATUS_UNSUPPORTED_STATUS; > > > > + ResponseMessage.Data.Response =3D &ResponseData; > > > > + Context->ResponseToken.Event =3D NULL; > > > > + CanMeasureTime =3D FALSE; > > > > + if (Context->Flags & DL_FLAG_TIME) { > > > > + ZeroMem (&StartTime, sizeof (StartTime)); > > > > + CanMeasureTime =3D !EFI_ERROR (gRT->GetTime (&StartTime, > NULL)); > > > > + } > > > > + > > > > + do { > > > > + SHELL_FREE_NON_NULL (ResponseMessage.Headers); > > > > + ResponseMessage.HeaderCount =3D 0; > > > > + gResponseCallbackComplete =3D FALSE; > > > > + ResponseMessage.BodyLength =3D Context->BufferSize; > > > > + > > > > + if (ShellGetExecutionBreakFlag ()) { > > > > + Status =3D EFI_ABORTED; > > > > + break; > > > > + } > > > > + > > > > + if (!Context->ContentDownloaded && !Context- > > > >ResponseToken.Event) { > > > > + Status =3D gBS->CreateEvent ( > > > > + EVT_NOTIFY_SIGNAL, > > > > + TPL_CALLBACK, > > > > + ResponseCallback, > > > > + Context, > > > > + &Context->ResponseToken.Event > > > > + ); > > > > + ASSERT_EFI_ERROR (Status); > > > > + } else { > > > > + ResponseMessage.Data.Response =3D NULL; > > > > + } > > > > + > > > > + if (EFI_ERROR (Status)) { > > > > + break; > > > > + } > > > > + > > > > + Status =3D Context->Http->Response (Context->Http, &Context- > > > > >ResponseToken); > > > > + if (EFI_ERROR (Status)) { > > > > + break; > > > > + } > > > > + > > > > + Status =3D WaitForCompletion (Context, > &gResponseCallbackComplete); > > > > + if (EFI_ERROR (Status) && ResponseMessage.HeaderCount) { > > > > + Status =3D 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 =3D REQ_NEED_REPEAT; > > > > + > > > > + Header =3D HttpFindHeader ( > > > > + ResponseMessage.HeaderCount, > > > > + ResponseMessage.Headers, > > > > + "Location" > > > > + ); > > > > + if (Header) { > > > > + Status =3D SetHostURI (Header->FieldValue, Context, > > DownloadUrl); > > > > + if (Status =3D=3D 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 =3D EFI_NOT_FOUND; > > > > + } > > > > + > > > > + Context->Http->Cancel (Context->Http, > > &Context->ResponseToken); > > > > + break; > > > > + } > > > > + > > > > + // > > > > + // Init message-body parser by header information. > > > > + // > > > > + if (!MsgParser) { > > > > + Status =3D 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 =3D HttpFindHeader ( > > > > + ResponseMessage.HeaderCount, > > > > + ResponseMessage.Headers, > > > > + "Transfer-Encoding" > > > > + ); > > > > + IsTrunked =3D (Header && !AsciiStrCmp (Header->FieldValue, > > > "chunked")); > > > > + > > > > + HttpGetEntityLength (MsgParser, &Context->ContentLength); > > > > + > > > > + if (ResponseData.StatusCode >=3D > HTTP_STATUS_400_BAD_REQUEST > > > > + && (ResponseData.StatusCode !=3D > > > > HTTP_STATUS_308_PERMANENT_REDIRECT)) > > > > + { > > > > + // > > > > + // Server reported an error via Response code. > > > > + // Collect the body if any. > > > > + // > > > > + if (!gHttpError) { > > > > + gHttpError =3D TRUE; > > > > + > > > > + Desc =3D 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 =3D ShellStrToUintn (Desc); > > > > + Status =3D ENCODE_ERROR (Context->Status); > > > > + } > > > > + } > > > > + } > > > > + > > > > + // Do NOT try to parse an empty body. > > > > + if (ResponseMessage.BodyLength || IsTrunked) { > > > > + Status =3D HttpParseMessageBody ( > > > > + MsgParser, > > > > + ResponseMessage.BodyLength, > > > > + ResponseMessage.Body > > > > + ); > > > > + } > > > > + } while (!HttpIsMessageComplete (MsgParser) > > > > + && !EFI_ERROR (Status) > > > > + && ResponseMessage.BodyLength); > > > > + > > > > + if (Context->Status !=3D REQ_NEED_REPEAT > > > > + && Status =3D=3D EFI_SUCCESS > > > > + && CanMeasureTime) > > > > + { > > > > + if (!EFI_ERROR (gRT->GetTime (&EndTime, NULL))) { > > > > + ElapsedSeconds =3D EfiTimeToEpoch (&EndTime) - > EfiTimeToEpoch > > > > (&StartTime); > > > > + Print ( > > > > + L",%a%us\n", > > > > + ElapsedSeconds ? " " : " < ", > > > > + ElapsedSeconds > 1 ? 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. > > > > + #retval EFI_HTTP_ERROR The server returned a valid > HTTP > > error. > > > > + Examine the mLocalFilePath > file > > > > + to get error body. > > > > + @retval Others The downloading of the file > from the > > server > > > > + failed. > > > > + > > > > +**/ > > > > +STATIC > > > > +EFI_STATUS > > > > +DownloadFile ( > > > > + IN 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) { > > > > + return EFI_INVALID_PARAMETER; > > > > + } > > > > + > > > > + DownloadUrl =3D NULL; > > > > + HttpChildHandle =3D NULL; > > > > + > > > > + Context->Buffer =3D AllocatePool (Context->BufferSize); > > > > + if (!Context->Buffer) { > > > > + Status =3D EFI_OUT_OF_RESOURCES; > > > > + goto ON_EXIT; > > > > + } > > > > + > > > > + // > > > > + // OPEN FILE > > > > + // > > > > + if (!EFI_ERROR (ShellFileExists (mLocalFilePath))) { > > > > + ShellDeleteFileByName (mLocalFilePath); > > > > + } > > > > + > > > > + Status =3D 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 =3D 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 =3D 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 =3D 0; > > > > + DownloadUrl =3D StrnCatGrow ( > > > > + &DownloadUrl, > > > > + &UrlSize, > > > > + Context->ServerAddrAndProto, > > > > + StrLen (Context->ServerAddrAndProto) > > > > + ); > > > > + if (Context->URI[0] !=3D L'/') { > > > > + DownloadUrl =3D StrnCatGrow ( > > > > + &DownloadUrl, > > > > + &UrlSize, > > > > + L"/", > > > > + StrLen (Context->ServerAddrAndProto) > > > > + ); > > > > + } > > > > + > > > > + DownloadUrl =3D StrnCatGrow ( > > > > + &DownloadUrl, > > > > + &UrlSize, > > > > + Context->URI, > > > > + StrLen (Context->URI)); > > > > + > > > > + PRINT_HII (STRING_TOKEN (STR_HTTP_DOWNLOADING), > > > DownloadUrl); > > > > + > > > > + Status =3D SendRequest (Context, DownloadUrl); > > > > + if (Status) { > > > > + goto ON_EXIT; > > > > + } > > > > + > > > > + Status =3D GetResponse (Context, DownloadUrl); > > > > + > > > > + if (Status) { > > > > + goto ON_EXIT; > > > > + } > > > > + > > > > + } while (Context->Status =3D=3D REQ_NEED_REPEAT); > > > > + > > > > + if (Context->Status) { > > > > + Status =3D ENCODE_ERROR (Context->Status); > > > > + } > > > > + > > > > +ON_EXIT: > > > > + // > > > > + // CLOSE FILE > > > > + // > > > > + if (mFileHandle) { > > > > + 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 ImageHandle The image handle of the > process. > > > > + > > > > + @return HII handle. > > > > +**/ > > > > +EFI_HII_HANDLE > > > > +InitializeHiiPackage ( > > > > + EFI_HANDLE ImageHandle > > > > + ) > > > > +{ > > > > + EFI_STATUS Status; > > > > + EFI_HII_PACKAGE_LIST_HEADER *PackageList; > > > > + EFI_HII_HANDLE HiiHandle; > > > > + > > > > + // > > > > + // Retrieve HII package list from ImageHandle > > > > + // > > > > + Status =3D 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 =3D 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 reserv= ed. > >
> > > > + 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 w= ill > > > > + * 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 =3D 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 =3D InitializeHiiPackage (ImageHandle); > > > > + if (mHttpHiiHandle =3D=3D NULL) { > > > > + return EFI_ABORTED; > > > > + } > > > > + > > > > + Status =3D EFI_SUCCESS; > > > > + > > > > + ShellStatus =3D RunHttp (ImageHandle, SystemTable); > > > > + > > > > + HiiRemovePackages (mHttpHiiHandle); > > > > + > > > > + if (Status !=3D SHELL_SUCCESS) { > > > > + Status =3D 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 reserv= ed. > >
> > > > + 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 typ= e. > > 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 protoco= l > > 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 =3D ShellParameters; > > > > + gEfiShellProtocol =3D 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 us= e. > > > > + > > > > + @return string Pool allocated help string, must be free= d 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 > > > =3D { > > > > + 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 =3D InitializeHiiPackage (ImageHandle); > > > > + if (mHttpHiiHandle =3D=3D NULL) { > > > > + return EFI_ABORTED; > > > > + } > > > > + > > > > + Status =3D 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 =3D 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 reser= ved. > >
> > > > +// 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 > > > > +// > > > > +// > > > > +// **/ > > > > + > > > > +/=3D# > > > > + > > > > +#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 wil= l be > > deleted.\r\n" > > > > +" -l port - Specifies the local port number. Default va= lue > > 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 doe= s > > not imply\r\n" > > > > +" better speed.\r\n" > > > > +" -t timeout - The number of seconds to wait for completio= n > > 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 addr= ess. > > If > > > the\r\n" > > > > +" optional 'localfilepath' parameter is provided, the downloa= ded > > file > > > is\r\n" > > > > +" stored locally using the provided file path. If the local f= ile > > 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 intend= ed > > 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. Otherwi= se, > > 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-lik= e > > 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 int= o > > 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.26.2.266.ge870325ee8 > > > > > > > > > > > > > > > > >=20 >=20 >=20