From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by mx.groups.io with SMTP id smtpd.web10.6673.1600309709952431341 for ; Wed, 16 Sep 2020 19:28:30 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@intel.onmicrosoft.com header.s=selector2-intel-onmicrosoft-com header.b=PXja1s94; spf=pass (domain: intel.com, ip: 192.55.52.93, mailfrom: zhichao.gao@intel.com) IronPort-SDR: 3f1nsCtjfnFfvfYlCIj/IF3KPBseMRsfYMxEeynGg8P96voZ+17SBPxEHLOj3LUQktMLEr8hrX K9i4xvAMQx2w== X-IronPort-AV: E=McAfee;i="6000,8403,9746"; a="157014306" X-IronPort-AV: E=Sophos;i="5.76,434,1592895600"; d="scan'208";a="157014306" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Sep 2020 19:28:28 -0700 IronPort-SDR: Jzm2fQTN+udc3MWiKvNNAnVR1e2LtqEeoWd5I2PAdWmrHUqqXceSEAd0/G+69H0AJkTu+fHUYo K5C3YsW2RFqQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,434,1592895600"; d="scan'208";a="346444746" Received: from fmsmsx603.amr.corp.intel.com ([10.18.126.83]) by orsmga007.jf.intel.com with ESMTP; 16 Sep 2020 19:28:28 -0700 Received: from fmsmsx609.amr.corp.intel.com (10.18.126.89) by fmsmsx603.amr.corp.intel.com (10.18.126.83) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1713.5; Wed, 16 Sep 2020 19:28:27 -0700 Received: from fmsmsx607.amr.corp.intel.com (10.18.126.87) by fmsmsx609.amr.corp.intel.com (10.18.126.89) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1713.5; Wed, 16 Sep 2020 19:28:27 -0700 Received: from fmsedg601.ED.cps.intel.com (10.1.192.135) by fmsmsx607.amr.corp.intel.com (10.18.126.87) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1713.5 via Frontend Transport; Wed, 16 Sep 2020 19:28:27 -0700 Received: from NAM12-DM6-obe.outbound.protection.outlook.com (104.47.59.170) by edgegateway.intel.com (192.55.55.70) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.1713.5; Wed, 16 Sep 2020 19:28:26 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=TbYAVNjyli8ri0sJUwSW1nA3qkSHtAjjDsLK2oJ6HB0q5fj69VZAQjoCn6B01js1Frv4J4Kgu83imxbO17A4m/IG0mT6pJYuf1ig5MRpT/olyCChBI0yoqc82e0+bK0PKPQ6aJ7YbMxhsxUjZ18QJp+fgrN6Q8RRuQS968e5px1Ztr2O4vkrif2GnHKTaYMcidZCckyCfsFyjymTKIF8Awr25fENM2xGwm/RMsWj0qpsfqTNxvPSx4Wf3ZgJLUSE2vqzJsKy9efz1XuUdibH1YOjuAi3g1ceCCUhjylR5n3ir3+JYDmLJt+Ges2ALDZ2Qh1g3RjufQOC6MleoHbNmw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=XHaFtQ7Mjv8fEkx5x7MlDOSNMNfB7WeAjPjjBlk9k6Q=; b=PVJed4OEPEgkgdx7n/RbtZa1I6bpJwoXg5SEezxkS/nykFD4FSrC4Z7z+O8OH9pGNpMy5VaLz47M4jkF/3fvuR6LSrlxpEEK46/Iz2tgMbsvw1eHuCpkzdkR/nVRDta6ZwSoJFjaYMgBO3Q7dktQMkua5rx2yurfgEdonsWHWVICxRojVU1+iAlTdT643sT9KulaA81FrOXGtSVHIZimbCuB2Afv0Gr3Oksf4rnKCryATAJvRtRF+BsnZaLLZ6C9kEZgPFMWaMdiRx4IiMoOF6kdeWTgjjQKMCUIgX+fNno6NYs+ZYzjOgopG7NVo00XNvDs+JiaixQsmpM7Hkvm7A== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=intel.com; dmarc=pass action=none header.from=intel.com; dkim=pass header.d=intel.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=intel.onmicrosoft.com; s=selector2-intel-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=XHaFtQ7Mjv8fEkx5x7MlDOSNMNfB7WeAjPjjBlk9k6Q=; b=PXja1s94Oal6MncHOnIUxrw5jiDWxyaaQpRxLycRiJSSYwKT4itpmyvAsy+FSniNgNBiBvu/lmvF425qu6u707MQFP8KzU8/uW3rB4fSgLhdAlNmRhOgKO8KnccAvQHpdxeRJX5MjddwG5hyOsQCOFQ2T8Jdo3Yh8qqijpZ+GcA= Received: from DM6PR11MB4425.namprd11.prod.outlook.com (2603:10b6:5:1d9::31) by DM6PR11MB3884.namprd11.prod.outlook.com (2603:10b6:5:19b::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3370.16; Thu, 17 Sep 2020 02:28:24 +0000 Received: from DM6PR11MB4425.namprd11.prod.outlook.com ([fe80::8dc1:7146:874:83f7]) by DM6PR11MB4425.namprd11.prod.outlook.com ([fe80::8dc1:7146:874:83f7%6]) with mapi id 15.20.3370.019; Thu, 17 Sep 2020 02:28:24 +0000 From: "Gao, Zhichao" To: "devel@edk2.groups.io" , "vladimir.olovyannikov@broadcom.com" CC: Samer El-Haj-Mahmoud , Laszlo Ersek , Maciej Rabeda , "Wu, Jiaxin" , "Fu, Siyuan" , "Ni, Ray" , Nd , gaoliming Subject: Re: [edk2-devel] [PATCH v12 1/1] ShellPkg/DynamicCommand: add HttpDynamicCommand Thread-Topic: [edk2-devel] [PATCH v12 1/1] ShellPkg/DynamicCommand: add HttpDynamicCommand Thread-Index: AQHWi4rErV6RodvctkGS87DCljHZTqlsEiKA Date: Thu, 17 Sep 2020 02:28:24 +0000 Message-ID: References: <20200915180416.8341-1-vladimir.olovyannikov@broadcom.com> <20200915180416.8341-2-vladimir.olovyannikov@broadcom.com> In-Reply-To: <20200915180416.8341-2-vladimir.olovyannikov@broadcom.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-product: dlpe-windows dlp-reaction: no-action dlp-version: 11.5.1.3 authentication-results: edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=none action=none header.from=intel.com; x-originating-ip: [192.55.46.36] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 3fc18a3d-5f32-469b-1d95-08d85ab15a58 x-ms-traffictypediagnostic: DM6PR11MB3884: x-ms-exchange-transport-forked: True x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:1923; x-ms-exchange-senderadcheck: 1 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: Qn+LD312jhPq3DsFuGvvrJhAiAUQutCcozcfsFrbNHEmwv93Pf9bXAejcwSXs7/8S5XIttzmhkeRrGemtKVu1Esphw8HInjP2JrgYuD1im79Rjut9pimG2U+7CY1WujhptMLvtg6jiHujq56EmZPWLyP2vfbJSHb2jfG0xCIVB3lxgAg+a50wEM0T6xI+8AwfXEBdZTiWU1x7higvIwkXQKyYleDLcXp8+kSLQcLnpJL3X7ydjw7FFacHb6+7FLO+OZscGnJ5bdzOvN06AG+sM32nzunzJ3fU/UPYZ+BPnVy1imqSoY06vZLyPatwEGH+D6mDv8OZ/0hYUK7skoDalAEa5MXEBWIS4jswM91/J4KVwQsjvI9rLIR/TquGYfq6rJPm+JTg8472o5BEORlgbgFVF2ljS9uoDaKsycXRfWtOdpELF2RNS4u7ncClTqdDe5YTBAoAfosevCacpjyYg== x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DM6PR11MB4425.namprd11.prod.outlook.com;PTR:;CAT:NONE;SFS:(6019001)(4636009)(366004)(39860400002)(346002)(376002)(396003)(136003)(54906003)(66946007)(66446008)(66476007)(66556008)(64756008)(8676002)(110136005)(7696005)(2906002)(966005)(8936002)(6506007)(71200400001)(86362001)(186003)(76116006)(83080400001)(83380400001)(9686003)(55016002)(26005)(4326008)(33656002)(52536014)(316002)(53546011)(5660300002)(30864003)(19627235002)(478600001)(16940595002)(559001)(579004);DIR:OUT;SFP:1102; x-ms-exchange-antispam-messagedata: Nbtgn9V0Az4jgZJPOZPKIhxoAcHcKR0LPxfZgqk6ERA4WF1nfyz+eYXU/zHPFXLXuXWsZHuwFvyXXIsfUlipgppot7S/Ono83Nd+tz8OO0ehyBQDBpQYoc8Xd34huT6S1vvunVRLD356mxe2TJuuGgqp5BzoDVcAEtTjeWYpTJ+FguYrm2bMdbXL2fjAe5uXIesukec/pQcwYiY4rWAUGapbLmVUtacZrPNgbyWt/MK0W6pqtoR5q1wNFbJn49zP+5Q7+5BsatA4pOA440DQqXQdrbQfcnokPPkIS7FQRxdYN+L86ztSUvppl5M0mckJbh1MmXSdSM5xz1S01zJ5iJit3zdauAAbptq0Hyl0Vdj6FovzstF+4HInSyerZRYfN3o9Ym6bj/Jz5MFPdHFK86iT9HmQDvUL+6dbVKeAF9XPHNsFaAWdkJRax3UmcBjcSVQhXbwlaWlXv0AsSPS46LHrNLOXDNCA5CHDdnc4eca238uaSwu/A/UTEpbu8fueJ/BfVtmWaQ/Po26CB82ZEDXZNLJ5CCBYWbylDlulsSqaosB5RkchrUHuggZBQoWUOhiUVERFSStSCro2s+qBwfPL0uWDQ0kMkfczIIwGuA4D4DalLlEJgozL/tBBb9hrOq8PgAfM6qMOJCUrys5Blg== MIME-Version: 1.0 X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: DM6PR11MB4425.namprd11.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 3fc18a3d-5f32-469b-1d95-08d85ab15a58 X-MS-Exchange-CrossTenant-originalarrivaltime: 17 Sep 2020 02:28:24.2111 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 46c98d88-e344-4ed4-8496-4ed7712e255d X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: lbQyY3ibh3HCoAozNdV5mdAvJTJeKP1N7lqP6NOBPHkD+KgWNKJbAh+GzTuuxqH/lj6m0Jmv4UQkmoHmBKLJ2g== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR11MB3884 Return-Path: zhichao.gao@intel.com X-OriginatorOrg: intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Hi Vladimir, Change Liming's email address. I have created one P-R for the patch to see the open-CI result. Seems it s= till some error about the coding style: 1. No doxygen tags in comment 2. mismatch parameters between comments and function definition 3. Comment description should end with '.' ... Please refer to https://github.com/tianocore/edk2/pull/934/checks?check_ru= n_id=3D1126330441 to see the error and fix it. Thanks, Zhichao > -----Original Message----- > From: devel@edk2.groups.io On Behalf Of Vladimir > Olovyannikov via groups.io > Sent: Wednesday, September 16, 2020 2:04 AM > To: devel@edk2.groups.io > Cc: Vladimir Olovyannikov ; Samer El= - > Haj-Mahmoud ; Laszlo Ersek > ; Gao, Zhichao ; Maciej Rabeda > ; Wu, Jiaxin ; Fu, S= iyuan > ; Ni, Ray ; Gao, Liming > ; Nd > Subject: [edk2-devel] [PATCH v12 1/1] ShellPkg/DynamicCommand: add > HttpDynamicCommand >=20 > 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=3D2860 >=20 > 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 | 1843 > +++++++++++++++++ > .../HttpDynamicCommand/HttpApp.c | 61 + > .../HttpDynamicCommand/HttpDynamicCommand.c | 137 ++ > .../HttpDynamicCommand/Http.uni | 117 ++ > 10 files changed, 2380 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 >=20 > 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, {0xb= 0, 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, {0x8= f, 0xf7, 0xc1, > 0xbd, 0xf1, 0xb2, 0x0e, 0xd4}} > + gShellHttpHiiGuid =3D {0x390f84b3, 0x221c, 0x4d9e, {0xb= 5, 0x06, 0x6d, > 0xb9, 0x42, 0x3e, 0x0a, 0x7e}} > gShellBcfgHiiGuid =3D {0x5f5f605d, 0x1583, 0x4a2d, {0xa= 6, 0xb2, 0xeb, > 0x12, 0xda, 0xb4, 0xa2, 0xb6}} > gShellAcpiViewHiiGuid =3D {0xda8ccdf4, 0xed8f, 0x4ffc, {0xb= 5, 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 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 =3D 0x00010006 > + BASE_NAME =3D http > + FILE_GUID =3D 56B00FB7-91D2-869B-CE5C-26CD1A89C7= 3C > + MODULE_TYPE =3D UEFI_APPLICATION > + VERSION_STRING =3D 1.0 > + ENTRY_POINT =3D HttpAppInitialize > +# > +# This flag specifies whether HII resource section is generated into P= E 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/HttpDynamicCommand.in > f > b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.in > f > new file mode 100644 > index 000000000000..5d46ee2384d5 > --- /dev/null > +++ > b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.in > f > @@ -0,0 +1,63 @@ > +## @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 =3D 0x00010006 > + BASE_NAME =3D httpDynamicCommand > + FILE_GUID =3D 19618BCE-55AE-09C6-37E9-4CE04084C7= A1 > + 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 P= E 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 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 > + ); > + > +/** > + 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, 0xb2, 0= x0e, 0xd4 } > \ > } >=20 > +#define SHELL_HTTP_HII_GUID \ > + { \ > + 0x390f84b3, 0x221c, 0x4d9e, { 0xb5, 0x06, 0x6d, 0xb9, 0x42, 0x3e, 0= x0a, > 0x7e } \ > + } >=20 > #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; >=20 > #endif > diff --git a/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c > b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c > new file mode 100644 > index 000000000000..3f11c1cd84c3 > --- /dev/null > +++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c > @@ -0,0 +1,1843 @@ > +/** @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 >=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 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. > +// TODO: remove 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[] =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' command > + > + @param[in] ValueStr Value as an Unicode encoded string > + @param[out] Value UINT16 value > + > + @return TRUE The value was returned. > + @return FALSE A parsing error occured. > +**/ > +STATIC > +BOOLEAN > +StringToUint16 ( > + IN CONST CHAR16 *ValueStr, > + OUT UINT16 *Value > + ); > + > +/** > + Get the name of the NIC. > + > + @param[in] ControllerHandle The network physical device handle. > + @param[in] NicNumber The network physical device number. > + @param[out] NicName Address where to store the NIC name. > + The memory area has to be at least > + IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH > + double byte wide. > + > + @return EFI_SUCCESS The name of the NIC was returned. > + @return Others The creation of the child for the Managed > + Network Service failed or the opening of > + the Managed Network Protocol failed or > + the operational parameters for the > + Managed Network Protocol could not be > + read. > +**/ > +STATIC > +EFI_STATUS > +GetNicName ( > + IN EFI_HANDLE ControllerHandle, > + IN UINTN NicNumber, > + OUT CHAR16 *NicName > + ); > + > +/** > + Create a child for the service identified by its service binding prot= ocol GUID > + and get from the child the interface of the protocol identified by it= s GUID. > + > + @param[in] ControllerHandle Controller handle. > + @param[in] ServiceBindingProtocolGuid Service binding protocol GUI= D of the > + service to be created. > + @param[in] ProtocolGuid GUID of the protocol to be o= pen. > + @param[out] ChildHandle Address where the handler of= the > + created child is returned. N= ULL is > + returned in case of error. > + @param[out] Interface Address where a pointer to t= he > + protocol interface is return= ed in > + case of success. > + > + @return EFI_SUCCESS The child was created and the protocol opened. > + @return Others Either the creation of the child or the opening > + of the protocol failed. > +**/ > +STATIC > +EFI_STATUS > +CreateServiceChildAndOpenProtocol ( > + IN EFI_HANDLE ControllerHandle, > + IN EFI_GUID *ServiceBindingProtocolGuid, > + IN EFI_GUID *ProtocolGuid, > + OUT EFI_HANDLE *ChildHandle, > + OUT VOID **Interface > + ); > + > +/** > + Close the protocol identified by its GUID on the child handle of the = service > + identified by its service binding protocol GUID, then destroy the chi= ld > + 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 cl= osed. > + @param[in] ChildHandle Handle of the child to be des= troyed. > + > +**/ > +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; > +} > + > +// > +// Set of functions from TimeBaseLib. > +// TODO: remove once TimeBaseLib gets fixed, and enabled for ShellPkg. > +// > + > +/** > + Calculate Epoch days > + **/ > +STATIC > +UINTN > +EfiGetEpochDays ( > + IN EFI_TIME *Time > + ) > +{ > + UINTN a; > + UINTN y; > + UINTN m; > + UINTN JulianDate; // Absolute Julian Date representation of the suppl= ied 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 > +UINTN > +EFIAPI > +EfiTimeToEpoch ( > + IN EFI_TIME *Time > + ) > +{ > + UINTN EpochDays; // Number of days elapsed since EPOCH_JULIAN_DAY > + UINTN 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 succes= sfully. > + @return SHELL_ABORTED The Shell Library initialization fa= iled. > + @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 erro= r 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_LENGT= H]; > + 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 with > + // 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' command > + > + @param[in] ValueStr Value as an Unicode encoded string > + @param[out] Value UINT16 value > + > + @return TRUE The value was returned. > + @return FALSE A parsing error occured. > +**/ > +STATIC > +BOOLEAN > +StringToUint16 ( > + IN CONST CHAR16 *ValueStr, > + OUT UINT16 *Value > + ) > +{ > + UINTN Val; > + > + Val =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 binding prot= ocol GUID > + and get from the child the interface of the protocol identified by it= s GUID. > + > + @param[in] ControllerHandle Controller handle. > + @param[in] ServiceBindingProtocolGuid Service binding protocol GUI= D of the > + service to be created. > + @param[in] ProtocolGuid GUID of the protocol to be o= pen. > + @param[out] ChildHandle Address where the handler of= the > + created child is returned. N= ULL is > + returned in case of error. > + @param[out] Interface Address where a pointer to t= he > + protocol interface is return= ed 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 of the = service > + identified by its service binding protocol GUID, then destroy the chi= ld > + 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 cl= osed. > + @param[in] ChildHandle Handle of the child to be des= troyed. > + > +**/ > +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 conte= xt. > + @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 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 =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 (StringSize); > + 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->RequestTo= ken); > + 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 receive= d. > + > + @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, Statu= s); > + 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_ST= EPS) / > + Context->ContentLength; > + } > + > + Context->LastReportedNbOfBytes =3D Context->ContentDownloaded; > + > + if (Step <=3D 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 =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 once, > + // 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) || !Context)= { > + return EFI_SUCCESS; > + } > + > + return SavePortion (Context, Length, Data); > +} > + > + > +/** > + Get HTTP server response and collect the whole body as a file. > + Set appropriate status in Context (REQ_OK, REQ_REPEAT, REQ_ERROR). > + Note that even if HTTP server returns an error code, it might send > + the body as well. This body will be collected in the resultant file. > + > + @param[in] Context A pointer to the HTTP download context. > + @param[in] DownloadedUrl A pointer to the fully qualified URL to = download. > + > + @return EFI_SUCCESS Valid file. Body successfully collected. > + @return EFI_HTTP_ERROR Response is a valid HTTP response, but t= he > + 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 redirec= ted). > + // > + Context->Status =3D REQ_NEED_REPEAT; > + > + Header =3D HttpFindHeader ( > + ResponseMessage.HeaderCount, > + ResponseMessage.Headers, > + "Location" > + ); > + if (Header) { > + Status =3D SetHostURI (Header->FieldValue, Context, DownloadU= rl); > + 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 locatio= n. > + // Indicate that resource was not found, and no body collecte= d. > + // > + 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, "chunk= ed")); > + > + 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%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 co= ntroller > + @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 s= erver > + 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 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 She= ll. > + */ > +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 comman= d. > +**/ > +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/HttpDynamicCommand.c > b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.c > new file mode 100644 > index 000000000000..7f59cc74d2a7 > --- /dev/null > +++ > b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.c > @@ -0,0 +1,137 @@ > +/** @file > + Produce "http" shell dynamic command. > + > + Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved. > + 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. Th= is > + 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 comm= and. > + @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 =3D ShellParameters; > + gEfiShellProtocol =3D Shell; > + > + return RunHttp (gImageHandle, SystemTable); > +} > + > +/** > + This is the command help handler function pointer callback type. Thi= s > + function is responsible for displaying help information for the assoc= iated > + 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 c= aller > +**/ > +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 comman= d. > +**/ > +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 reserved. <= BR> > +// 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 fla= g - > '%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 interfac= e > card found.\r\n" > +#string STR_HTTP_ERR_NIC_NAME #language en-US "Failed to get the n= ame > 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 int= o 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 err= or.\r\n" > +" If this parameter is not used, the file will be d= eleted.\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 b= ytes.\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 'au= tomatic'.\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. I= f the\r\n" > +" optional 'localfilepath' parameter is provided, the downloaded fi= le is\r\n" > +" stored locally using the provided file path. If the local file pa= th 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, al= l > network\r\n" > +" interfaces are tried in the order they have been discovered durin= g 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 po= rt 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 s= tatus > 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 comm= and line, > +" the file wil be saved either as localfilep= ath filename,\r\n" > +" or as an URI name in the current directory= .\r\n" > +" If '/' is at the end of the URL, and no lo= cafilepath filename\r\n" > +" is given on the command line, the file wil= l be retrieved as\r\n" > +" index.html.\r\n" > -- > 2.28.0.394.ge197136389 >=20 >=20 >=20