From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by mx.groups.io with SMTP id smtpd.web12.35060.1597628885092060037 for ; Sun, 16 Aug 2020 18:48:05 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@intel.onmicrosoft.com header.s=selector2-intel-onmicrosoft-com header.b=GDA/jxqr; spf=pass (domain: intel.com, ip: 192.55.52.88, mailfrom: zhichao.gao@intel.com) IronPort-SDR: 3KyjVFaLPfBappLr5zT3RaFIHRumA2FGFxmEH1fUyJ+vim3vrwwcDz8CDSRqNeJrhcJpnAQbAi XdtL8Drbdyzw== X-IronPort-AV: E=McAfee;i="6000,8403,9715"; a="172675407" X-IronPort-AV: E=Sophos;i="5.76,322,1592895600"; d="scan'208";a="172675407" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Aug 2020 18:48:03 -0700 IronPort-SDR: OAx9qlH4f2s/aZptzeKgyWXvYRhtcqCjiHbnQlYbzz8KV3QUyCYuy3gbkfI3ArzdesETvKJcao J51EwJUfHVtQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,322,1592895600"; d="scan'208";a="400023275" Received: from unknown (HELO fmsmsx605.amr.corp.intel.com) ([10.18.84.215]) by fmsmga001.fm.intel.com with ESMTP; 16 Aug 2020 18:48:03 -0700 Received: from fmsmsx611.amr.corp.intel.com (10.18.126.91) by fmsmsx605.amr.corp.intel.com (10.18.126.85) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1713.5; Sun, 16 Aug 2020 18:48:02 -0700 Received: from FMSEDG001.ED.cps.intel.com (10.1.192.133) by fmsmsx611.amr.corp.intel.com (10.18.126.91) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.1.1713.5 via Frontend Transport; Sun, 16 Aug 2020 18:48:02 -0700 Received: from NAM12-MW2-obe.outbound.protection.outlook.com (104.47.66.46) by edgegateway.intel.com (192.55.55.68) with Microsoft SMTP Server (TLS) id 14.3.439.0; Sun, 16 Aug 2020 18:47:58 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ZW6aqXiONYirkkIXPdCW6sD1Qz+EoBYFSdS/NYAlsqatULF50zfijlk/M9KY2Tw3NzHYv0P0DMrEgal2xBq5XI3/xZYk8ruLXYUOjj95YFdTOipSSEy6YYn2oENgO1cdMHHyKMoSD0BfLtI7zIBw/h2BIy8SAW7EhIFnIduRHvAmH3NmsBqln/lWZG0KPe2zB2Llvc2+ymUDFkRLxWXPXNFJHMrRz8yvmlRO5wuPtocDwkinjWCLj6s79iyZOuMEKJK4OQSrRplSrtkR5QU7AexH/CeV0+d3fneo8K/NUUyH1fSKnatBE/LKVEG5yXDZh9TTkkn1xfc0wDq1z1BxrA== 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=/RBdvg0y0WlQ7s1Ww3dNE9KflANKaGmkKcNhp+Lw8Ag=; b=MqrAfRdZvA5ux3TDmefBcgSlpEqMjh4FNmbRlU6P3KIrp+IHhuA3YdIWTowgypJM3iivDpRi20gotBX014jBk9BQUXnEmGzCkHMbhmuJybDyYncpdU1Qnz/nv1w1aoIpLbTpNtD4L7jk29Mnj3uQTqj9jdRPL9ao9LrtvQR4o3Gf1fcQZhUfDn4Y4eVjFO67NChcPUk6SZOIdxGiQymBThJyBAcuh3a/SyWzOkZzX87nNwULRKmWDW5JPtcQat1ChqKsNH2y8cR9EtOooGVGpBpGj0lwTgIhI0I/N8xLwq+vn5Kbogpz7It4+oJMFGvc3qsBMw/+d3GyaS3T11oTFw== 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=/RBdvg0y0WlQ7s1Ww3dNE9KflANKaGmkKcNhp+Lw8Ag=; b=GDA/jxqrsxzktju7vKkTf7psGJ5XOv1gqXRanPrVO/UImOhOw33mgnB6hI9kkHacrkAQbM56Y17d/gXEHjKvtOWNAO+6MoIW6TkpoC75kFqJlDaQLf7uHq+HINnso0UA7neNPsrsxc9COjR/g4v1csQqdnpojlfEtrFQsQzcKoM= Received: from DM6PR11MB4425.namprd11.prod.outlook.com (2603:10b6:5:1d9::31) by DM6PR11MB3963.namprd11.prod.outlook.com (2603:10b6:5:19b::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3283.18; Mon, 17 Aug 2020 01:47:47 +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.3283.027; Mon, 17 Aug 2020 01:47:47 +0000 From: "Gao, Zhichao" To: Vladimir Olovyannikov , "devel@edk2.groups.io" CC: Laszlo Ersek , Samer El-Haj-Mahmoud , Maciej Rabeda , "Wu, Jiaxin" , "Fu, Siyuan" , "Ni, Ray" , "Gao, Liming" , Nd Subject: Re: [PATCH v5 1/1] ShellPkg/DynamicCommand: add HttpDynamicCommand Thread-Topic: [PATCH v5 1/1] ShellPkg/DynamicCommand: add HttpDynamicCommand Thread-Index: AQHWZDXjbHJiVCsgG0iCAWKcdhlPCak7oUUw Date: Mon, 17 Aug 2020 01:47:47 +0000 Message-ID: References: <20200727164830.25829-1-vladimir.olovyannikov@broadcom.com> <20200727164830.25829-2-vladimir.olovyannikov@broadcom.com> In-Reply-To: <20200727164830.25829-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: broadcom.com; dkim=none (message not signed) header.d=none;broadcom.com; dmarc=none action=none header.from=intel.com; x-originating-ip: [192.102.204.38] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 1bb7bbbb-7643-4d36-bb6b-08d8424f8b20 x-ms-traffictypediagnostic: DM6PR11MB3963: x-ld-processed: 46c98d88-e344-4ed4-8496-4ed7712e255d,ExtAddr x-ms-exchange-transport-forked: True x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:353; x-ms-exchange-senderadcheck: 1 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: awnk9uCQepHzUS6FGLoqummXAgQgIAe0/mci52RECP6TN7bBwZ5Lgqvf2TxSexApjtnEqZpv7tPpHgTGEw0JneAQOxuR3pW2TybtGkGao3gXb3kcM9W8TTKabiPrmtSSu6pC7ZSOoc8qSypwXBhFfO6bmDWwsz1+2//CXtmbtFt2GEn2yKogza/YEV06lhg9z5MMel1eepdzxRLBf8K+JO1jQxAVzj8woeBH1TKJjtBI93g0Ch28WyGxGZqqH9bMT9QyUATK1ih0ZA1tN0xQYqXbq5Q4WlHrgN0BSlORJE0hMpE6mYguLreIApCrUHJbA3bxzk08q/iFNQLa/imdv5U1PCaHfCZutDsLt8p1eBtTe36/qeknmMNBjBf6Rs807XF2YXY6TxexjSB5gClp+yygoaBv2ILhNAllwPVq94g1BqQV3NjlhReKRKK1dcQgHhbacgHucCpjowp2gdgG1g== 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)(39860400002)(396003)(376002)(366004)(346002)(136003)(966005)(66946007)(2906002)(6506007)(55016002)(9686003)(54906003)(71200400001)(83380400001)(5660300002)(53546011)(110136005)(478600001)(76116006)(7696005)(52536014)(33656002)(66446008)(64756008)(66556008)(66476007)(19627235002)(83080400001)(4326008)(186003)(8676002)(8936002)(86362001)(30864003)(316002)(26005)(16940595002)(579004)(559001);DIR:OUT;SFP:1102; x-ms-exchange-antispam-messagedata: ZxDhA7N8PZleYXtO3OjyTaiBBxlzDcXHfhOykQHovUd42rXXFFqYTcxZL1zH5KDT6QQFq1JzEBl8iDPsq9PVbQUUn9zgkELtM70YqRqsl2VqCuLovrNGOom2LqS+dpPTJqy+wMYju2iJGEGfFOlejeLx+2VkMmGSRvd6xfk7wLxtYiBDAe+Ewem9yrA3S4Halr97Cvx9fkMgfYPiBoN8t3U3rJE5J0dBpNrlojhIM1f9g5leImCfZMM1xA5XSE3EMbSJBwiQJ5kC5vgKb27dT5c5p1IiefZgE0yliNKnUzNvFrCBd26MFREdDBj9D+UzIH7Q92Q/Fpu0yv5c42o0GwPFdVni9sdmGH/WqkcnCOQy12qAuPwKOSbtvooYjBhOZmXTIGixHARBbOcSyPAusqJPFF8TwbJDSP+WBvzcNlW2UZJ6RLuIaJNwrsDCW/AplDcmiG85LwJ6mIW5Fr0p0lqDCsaqwKzQIh3L4ZjxvYhZrkT5RtRI/mnPIyRzvLhDQqptOsg/VWp65TAGXFGlThd1UxKcUKET6+po06p7OUV8cDbGCpD7fz+e9jUABlTriGWEFxmXFHuCb1o0S1pagOyh9O0zamReDF8IH7iHI4bFJgG1vlHs2c+m2WZxJifpM++7MzDQjxryeoadCL6Xiw== 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: 1bb7bbbb-7643-4d36-bb6b-08d8424f8b20 X-MS-Exchange-CrossTenant-originalarrivaltime: 17 Aug 2020 01:47:47.4074 (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: 39h4qmcXa6nyHLRSgDo/sQs8kf9WNiYMb6kfs8t9ncqAs3ibqsrDT62GQO1y/Rnx5t3AcD8Li8H1fpD65xDXhw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR11MB3963 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 Sorry for the delay reply. See below: > -----Original Message----- > From: Vladimir Olovyannikov > Sent: Tuesday, July 28, 2020 12:49 AM > To: devel@edk2.groups.io > Cc: Laszlo Ersek ; Vladimir Olovyannikov > ; Samer El-Haj-Mahmoud Haj-Mahmoud@arm.com>; Gao, Zhichao ; Maciej > Rabeda ; Wu, Jiaxin ;= Fu, > Siyuan ; Ni, Ray ; Gao, Liming > ; Nd > Subject: [PATCH v5 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 > --- > CryptoPkg/Library/OpensslLib/openssl | 2 +- > .../DynamicCommand/HttpDynamicCommand/Http.c | 1715 > +++++++++++++++++ > .../DynamicCommand/HttpDynamicCommand/Http.h | 89 + > .../HttpDynamicCommand/Http.uni | 117 ++ > .../HttpDynamicCommand/HttpApp.c | 53 + > .../HttpDynamicCommand/HttpApp.inf | 58 + > .../HttpDynamicCommand/HttpDynamicCommand.c | 134 ++ > .../HttpDynamicCommand/HttpDynamicCommand.inf | 63 + > ShellPkg/Include/Guid/ShellLibHiiGuid.h | 5 + > ShellPkg/ShellPkg.dec | 1 + > ShellPkg/ShellPkg.dsc | 5 + > 11 files changed, 2241 insertions(+), 1 deletion(-) > create mode 100644 ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c > create mode 100644 > ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h > create mode 100644 > ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni > create mode 100644 > ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c > create mode 100644 > ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf > create mode 100644 > ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.c > create mode 100644 > ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf >=20 > diff --git a/CryptoPkg/Library/OpensslLib/openssl > b/CryptoPkg/Library/OpensslLib/openssl > index e2e09d9fba11..c3656cc594da 160000 > --- a/CryptoPkg/Library/OpensslLib/openssl > +++ b/CryptoPkg/Library/OpensslLib/openssl > @@ -1 +1 @@ > -Subproject commit e2e09d9fba1187f8d6aafaa34d4172f56f1ffb72 > +Subproject commit c3656cc594daac8167721dde7220f0e59ae146fc > diff --git a/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c > b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c > new file mode 100644 > index 000000000000..0565b07c3570 > --- /dev/null > +++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c > @@ -0,0 +1,1715 @@ > +/** @file >=20 > + The implementation for the 'http' Shell command. >=20 > + >=20 > + Copyright (c) 2015, ARM Ltd. All rights reserved.
>=20 > + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved. >=20 > + (C) Copyright 2015 Hewlett Packard Enterprise Development LP
>=20 > + Copyright (c) 2020, Broadcom. All rights reserved.
>=20 > + >=20 > + SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > +**/ >=20 > + >=20 > +#include "Http.h" >=20 > + >=20 > +#define IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH 32 >=20 > +EFI_HII_HANDLE mHttpHiiHandle; >=20 > + >=20 > +/* >=20 > + Constant strings and definitions related to the message >=20 > + indicating the amount of progress in the dowloading of a HTTP file. >=20 > +*/ >=20 > + >=20 > +// Number of steps in the progression slider >=20 > +#define HTTP_PROGRESS_SLIDER_STEPS \ >=20 > + ((sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) - 3) >=20 > + >=20 > +// Size in number of characters plus one (final zero) of the message to >=20 > +// indicate the progress of an HTTP download. The format is "[(progress = slider: >=20 > +// 40 characters)] (nb of KBytes downloaded so far: 7 characters) Kb". T= here >=20 > +// are thus the number of characters in HTTP_PROGR_FRAME[] plus 11 > characters >=20 > +// (2 // spaces, "Kb" and seven characters for the number of KBytes). >=20 > +#define HTTP_PROGRESS_MESSAGE_SIZE \ >=20 > + ((sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) + 12) >=20 > + >=20 > +// >=20 > +// Buffer size. Note that larger buffer does not mean better speed! >=20 > +// >=20 > +#define DEFAULT_BUF_SIZE SIZE_32KB >=20 > +#define MAX_BUF_SIZE SIZE_4MB >=20 > + >=20 > +#define MIN_PARAM_COUNT 2 >=20 > +#define MAX_PARAM_COUNT 4 >=20 > + >=20 > +#define TIMER_MAX_TIMEOUT_S 10 >=20 > + >=20 > +// File name to use when URI ends with "/" >=20 > +#define DEFAULT_HTML_FILE L"index.html" >=20 > +#define DEFAULT_HTTP_PROTO L"http" >=20 > + >=20 > +// String to delete the HTTP progress message to be able to update it : >=20 > +// (HTTP_PROGRESS_MESSAGE_SIZE-1) '\b' >=20 > +#define HTTP_PROGRESS_DEL \ >=20 > + 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\ >=20 > +\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" >=20 > + >=20 > +#define HTTP_KB L"\b\b\b\b\b\b\b\b\b\b" >=20 > +// Frame for the progression slider >=20 > +#define HTTP_PROGR_FRAME L"[ = ]" >=20 > + >=20 > +// String descriptions for server errors >=20 > +STATIC CONST CHAR16 *ErrStatusDesc[] =3D >=20 > +{ >=20 > + L"400 Bad Request", >=20 > + L"401 Unauthorized", >=20 > + L"402 Payment required", >=20 > + L"403 Forbidden", >=20 > + L"404 Not Found", >=20 > + L"405 Method not allowed", >=20 > + L"406 Not acceptable", >=20 > + L"407 Proxy authentication required", >=20 > + L"408 Request time out", >=20 > + L"409 Conflict", >=20 > + L"410 Gone", >=20 > + L"411 Length required", >=20 > + L"412 Precondition failed", >=20 > + L"413 Request entity too large", >=20 > + L"414 Request URI to large", >=20 > + L"415 Unsupported media type", >=20 > + L"416 Requested range not satisfied", >=20 > + L"417 Expectation failed", >=20 > + L"500 Internal server error", >=20 > + L"501 Not implemented", >=20 > + L"502 Bad gateway", >=20 > + L"503 Service unavailable", >=20 > + L"504 Gateway timeout", >=20 > + L"505 HTTP version not supported" >=20 > +}; >=20 > + >=20 > +// Local File Handle >=20 > +STATIC SHELL_FILE_HANDLE mFileHandle =3D NULL; >=20 > + >=20 > +// Path of the local file, Unicode encoded >=20 > +STATIC CONST CHAR16 *mLocalFilePath; >=20 > + >=20 > +STATIC BOOLEAN gRequestCallbackComplete =3D FALSE; >=20 > +STATIC BOOLEAN gResponseCallbackComplete =3D FALSE; >=20 > + >=20 > +STATIC BOOLEAN gHttpError; >=20 > + >=20 > +/** >=20 > + Cleans off leading and trailing spaces and tabs. >=20 > + >=20 > + @param[in] String pointer to the string to trim them off. >=20 > +**/ >=20 > +STATIC >=20 > +EFI_STATUS >=20 > +TrimSpaces ( >=20 > + IN CHAR16 **String >=20 > + ) >=20 > +{ >=20 > + ASSERT(String !=3D NULL); >=20 > + ASSERT(*String!=3D NULL); >=20 > + // >=20 > + // Remove any spaces and tabs at the beginning of the (*String). >=20 > + // >=20 > + while (((*String)[0] =3D=3D L' ') || ((*String)[0] =3D=3D L'\t')) { >=20 > + CopyMem ( >=20 > + (*String), >=20 > + (*String) + 1, >=20 > + StrSize ((*String)) - sizeof((*String)[0]) >=20 > + ); >=20 > + } >=20 > + >=20 > + // >=20 > + // Remove any spaces and tabs at the end of the (*String). >=20 > + // >=20 > + while ((StrLen (*String) > 0) && >=20 > + (((*String)[StrLen ((*String)) - 1] =3D=3D L' ') || >=20 > + ((*String)[StrLen ((*String)) - 1] =3D=3D L'\t')) >=20 > + ) { >=20 > + (*String)[StrLen ((*String)) - 1] =3D CHAR_NULL; >=20 > + } >=20 > + >=20 > + return (EFI_SUCCESS); >=20 > +} >=20 > + >=20 > + >=20 > +/* >=20 > + * Callbacks for request and response. >=20 > + * We just acknowledge that operation has completed here. >=20 > + */ >=20 > +STATIC >=20 > +VOID >=20 > +EFIAPI >=20 > +RequestCallback ( >=20 > + IN EFI_EVENT Event, >=20 > + IN VOID *Context >=20 > +) >=20 > +{ >=20 > + gRequestCallbackComplete =3D TRUE; >=20 > +} >=20 > + >=20 > +STATIC >=20 > +VOID >=20 > +EFIAPI >=20 > +ResponseCallback ( >=20 > + IN EFI_EVENT Event, >=20 > + IN VOID *Context >=20 > +) >=20 > +{ >=20 > + gResponseCallbackComplete =3D TRUE; >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + Check and convert the UINT16 option values of the 'http' command >=20 > + >=20 > + @param[in] ValueStr Value as an Unicode encoded string >=20 > + @param[out] Value UINT16 value >=20 > + >=20 > + @return TRUE The value was returned. >=20 > + @return FALSE A parsing error occured. >=20 > +**/ >=20 > +STATIC >=20 > +BOOLEAN >=20 > +StringToUint16 ( >=20 > + IN CONST CHAR16 *ValueStr, >=20 > + OUT UINT16 *Value >=20 > + ); >=20 > + >=20 > +/** >=20 > + Get the name of the NIC. >=20 > + >=20 > + @param[in] ControllerHandle The network physical device handle. >=20 > + @param[in] NicNumber The network physical device number. >=20 > + @param[out] NicName Address where to store the NIC name. >=20 > + The memory area has to be at least >=20 > + IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH >=20 > + double byte wide. >=20 > + >=20 > + @return EFI_SUCCESS The name of the NIC was returned. >=20 > + @return Others The creation of the child for the Managed >=20 > + Network Service failed or the opening of >=20 > + the Managed Network Protocol failed or >=20 > + the operational parameters for the >=20 > + Managed Network Protocol could not be >=20 > + read. >=20 > +**/ >=20 > +STATIC >=20 > +EFI_STATUS >=20 > +GetNicName ( >=20 > + IN EFI_HANDLE ControllerHandle, >=20 > + IN UINTN NicNumber, >=20 > + OUT CHAR16 *NicName >=20 > + ); >=20 > + >=20 > +/** >=20 > + Create a child for the service identified by its service binding proto= col GUID >=20 > + and get from the child the interface of the protocol identified by its= GUID. >=20 > + >=20 > + @param[in] ControllerHandle Controller handle. >=20 > + @param[in] ServiceBindingProtocolGuid Service binding protocol GUID= of the >=20 > + service to be created. >=20 > + @param[in] ProtocolGuid GUID of the protocol to be op= en. >=20 > + @param[out] ChildHandle Address where the handler of = the >=20 > + created child is returned. NU= LL is >=20 > + returned in case of error. >=20 > + @param[out] Interface Address where a pointer to th= e >=20 > + protocol interface is returne= d in >=20 > + case of success. >=20 > + >=20 > + @return EFI_SUCCESS The child was created and the protocol opened. >=20 > + @return Others Either the creation of the child or the opening >=20 > + of the protocol failed. >=20 > +**/ >=20 > +STATIC >=20 > +EFI_STATUS >=20 > +CreateServiceChildAndOpenProtocol ( >=20 > + IN EFI_HANDLE ControllerHandle, >=20 > + IN EFI_GUID *ServiceBindingProtocolGuid, >=20 > + IN EFI_GUID *ProtocolGuid, >=20 > + OUT EFI_HANDLE *ChildHandle, >=20 > + OUT VOID **Interface >=20 > + ); >=20 > + >=20 > +/** >=20 > + Close the protocol identified by its GUID on the child handle of the s= ervice >=20 > + identified by its service binding protocol GUID, then destroy the chil= d >=20 > + handle. >=20 > + >=20 > + @param[in] ControllerHandle Controller handle. >=20 > + @param[in] ServiceBindingProtocolGuid Service binding protocol GUID = of the >=20 > + service to be destroyed. >=20 > + @param[in] ProtocolGuid GUID of the protocol to be clo= sed. >=20 > + @param[in] ChildHandle Handle of the child to be dest= royed. >=20 > + >=20 > +**/ >=20 > +STATIC >=20 > +VOID >=20 > +CloseProtocolAndDestroyServiceChild ( >=20 > + IN EFI_HANDLE ControllerHandle, >=20 > + IN EFI_GUID *ServiceBindingProtocolGuid, >=20 > + IN EFI_GUID *ProtocolGuid, >=20 > + IN EFI_HANDLE ChildHandle >=20 > + ); >=20 > + >=20 > + >=20 > +/** >=20 > + Worker function that download the data of a file from an HTTP server g= iven >=20 > + the path of the file and its size. >=20 > + >=20 > + @param[in] Context A pointer to the download context. >=20 > + >=20 > + @retval EFI_SUCCESS The file was downloaded. >=20 > + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. >=20 > + @retval Others The downloading of the file >=20 > + from the server failed. >=20 > + >=20 > +**/ >=20 > +STATIC >=20 > +EFI_STATUS >=20 > +DownloadFile ( >=20 > + IN DOWNLOAD_CONTEXT *Context >=20 > + ); >=20 > + >=20 > +STATIC CONST SHELL_PARAM_ITEM ParamList[] =3D { >=20 > + {L"-i", TypeValue}, >=20 > + {L"-k", TypeFlag}, >=20 > + {L"-l", TypeValue}, >=20 > + {L"-s", TypeValue}, >=20 > + {L"-t", TypeValue}, >=20 > + {NULL , TypeMax} >=20 > + }; >=20 > + >=20 > +/** >=20 > + Function for 'http' command. >=20 > + >=20 > + @param[in] ImageHandle Handle to the Image (NULL if Internal). >=20 > + @param[in] SystemTable Pointer to the System Table (NULL if Internal)= . >=20 > + >=20 > + @return SHELL_SUCCESS The 'http' command completed success= fully. >=20 > + @return SHELL_ABORTED The Shell Library initialization fai= led. >=20 > + @return SHELL_INVALID_PARAMETER At least one of the command's > arguments is >=20 > + not valid. >=20 > + @return SHELL_OUT_OF_RESOURCES A memory allocation failed. >=20 > + @return SHELL_NOT_FOUND Network Interface Card not found. >=20 > + @return SHELL_UNSUPPORTED Command was valid, but the server > returned >=20 > + a status code indicating some error. >=20 > + Examine the file requested for error= body. >=20 > + >=20 > +**/ >=20 > +SHELL_STATUS >=20 > +RunHttp ( >=20 > + IN EFI_HANDLE ImageHandle, >=20 > + IN EFI_SYSTEM_TABLE *SystemTable >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + LIST_ENTRY *CheckPackage; >=20 > + UINTN ParamCount; >=20 > + UINTN HandleCount; >=20 > + UINTN NicNumber; >=20 > + UINTN InitialSize; >=20 > + UINTN ParamOffset; >=20 > + UINTN StartSize; >=20 > + CHAR16 *ProblemParam; >=20 > + CHAR16 NicName[IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH= ]; >=20 > + CHAR16 *Walker1; >=20 > + CHAR16 *VStr; >=20 > + CONST CHAR16 *UserNicName; >=20 > + CONST CHAR16 *ValueStr; >=20 > + CONST CHAR16 *RemoteFilePath; >=20 > + CONST CHAR16 *Walker; >=20 > + EFI_HTTP_CONFIG_DATA HttpConfigData; >=20 > + EFI_HTTPv4_ACCESS_POINT IPv4Node; >=20 > + EFI_HANDLE *Handles; >=20 > + EFI_HANDLE ControllerHandle; >=20 > + EFI_HANDLE HttpChildHandle; >=20 > + DOWNLOAD_CONTEXT Context; >=20 > + BOOLEAN NicFound; >=20 > + >=20 > + ProblemParam =3D NULL; >=20 > + RemoteFilePath =3D NULL; >=20 > + NicFound =3D FALSE; >=20 > + Handles =3D NULL; >=20 > + >=20 > + // >=20 > + // Initialize the Shell library (we must be in non-auto-init...) >=20 > + // >=20 > + ParamOffset =3D 0; >=20 > + gHttpError =3D FALSE; >=20 > + >=20 > + Status =3D ShellInitialize (); >=20 > + if (EFI_ERROR (Status)) { >=20 > + ASSERT_EFI_ERROR (Status); >=20 > + return SHELL_ABORTED; >=20 > + } >=20 > + >=20 > + ZeroMem (&Context, sizeof (Context)); >=20 > + >=20 > + // >=20 > + // Parse the command line. >=20 > + // >=20 > + Status =3D ShellCommandLineParse ( >=20 > + ParamList, >=20 > + &CheckPackage, >=20 > + &ProblemParam, >=20 > + TRUE); I prefer to put ');' in next line like other functions. >=20 > + if (EFI_ERROR (Status)) { >=20 > + if ((Status =3D=3D EFI_VOLUME_CORRUPTED) && >=20 > + (ProblemParam !=3D NULL) ) { >=20 > + ShellPrintHiiEx ( >=20 > + -1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), mHttpHiiHandle, >=20 > + HTTP_APP_NAME, ProblemParam >=20 > + ); >=20 > + SHELL_FREE_NON_NULL (ProblemParam); >=20 > + } else { >=20 > + ASSERT (FALSE); >=20 > + } >=20 > + >=20 > + goto Error; >=20 > + } >=20 > + >=20 > + // >=20 > + // Check the number of parameters >=20 > + // >=20 > + Status =3D EFI_INVALID_PARAMETER; >=20 > + >=20 > + ParamCount =3D ShellCommandLineGetCount (CheckPackage); >=20 > + if (ParamCount > MAX_PARAM_COUNT) { >=20 > + ShellPrintHiiEx ( >=20 > + -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), >=20 > + mHttpHiiHandle, HTTP_APP_NAME >=20 > + ); >=20 > + goto Error; >=20 > + } >=20 > + >=20 > + if (ParamCount < MIN_PARAM_COUNT) { >=20 > + ShellPrintHiiEx ( >=20 > + -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), >=20 > + mHttpHiiHandle, HTTP_APP_NAME >=20 > + ); >=20 > + goto Error; >=20 > + } >=20 > + >=20 > + ZeroMem (&HttpConfigData, sizeof (HttpConfigData)); >=20 > + ZeroMem (&IPv4Node, sizeof (IPv4Node)); >=20 > + IPv4Node.UseDefaultAddress =3D TRUE; >=20 > + >=20 > + HttpConfigData.HttpVersion =3D HttpVersion11; >=20 > + HttpConfigData.AccessPoint.IPv4Node =3D &IPv4Node; >=20 > + >=20 > + // >=20 > + // Get the host address (not necessarily IPv4 format) >=20 > + // >=20 > + ValueStr =3D ShellCommandLineGetRawValue (CheckPackage, 1); >=20 > + if (!ValueStr) { >=20 > + ShellPrintHiiEx ( >=20 > + -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), mHttpHiiHandle, >=20 > + HTTP_APP_NAME, ValueStr >=20 > + ); >=20 > + goto Error; >=20 > + } else { >=20 > + StartSize =3D 0; >=20 > + if (!StrStr (ValueStr, L"://")) { >=20 > + Context.ServerAddrAndProto =3D StrnCatGrow ( >=20 > + &Context.ServerAddrAndProto, >=20 > + &StartSize, >=20 > + DEFAULT_HTTP_PROTO, >=20 > + StrLen (DEFAULT_HTTP_PROTO) >=20 > + ); >=20 > + Context.ServerAddrAndProto =3D StrnCatGrow ( >=20 > + &Context.ServerAddrAndProto, >=20 > + &StartSize, >=20 > + L"://", >=20 > + StrLen (L"://") >=20 > + ); >=20 > + VStr =3D (CHAR16 *)ValueStr; >=20 > + } else { >=20 > + VStr =3D StrStr (ValueStr, L"://") + StrLen (L"://"); >=20 > + } >=20 > + >=20 > + for (Walker1 =3D VStr; *Walker1; Walker1++) { >=20 > + if (*Walker1 =3D=3D L'/') { >=20 > + break; >=20 > + } >=20 > + } >=20 > + >=20 > + if (*Walker1 =3D=3D L'/') { >=20 > + ParamOffset =3D 1; >=20 > + RemoteFilePath =3D Walker1; >=20 > + } >=20 > + >=20 > + Context.ServerAddrAndProto =3D StrnCatGrow ( >=20 > + &Context.ServerAddrAndProto, >=20 > + &StartSize, >=20 > + ValueStr, >=20 > + StrLen (ValueStr) - StrLen (Walker1) >=20 > + ); >=20 > + if (!Context.ServerAddrAndProto) { >=20 > + Status =3D EFI_OUT_OF_RESOURCES; >=20 > + goto Error; >=20 > + } >=20 > + } >=20 > + >=20 > + if (!RemoteFilePath) { >=20 > + RemoteFilePath =3D ShellCommandLineGetRawValue (CheckPackage, 2); >=20 > + if (!RemoteFilePath) { >=20 > + // If no path given, assume just "/" >=20 > + RemoteFilePath =3D L"/"; >=20 > + } >=20 > + } >=20 > + >=20 > + TrimSpaces ((CHAR16 **)&RemoteFilePath); >=20 > + >=20 > + if (ParamCount =3D=3D MAX_PARAM_COUNT - ParamOffset) { >=20 > + mLocalFilePath =3D ShellCommandLineGetRawValue ( >=20 > + CheckPackage, >=20 > + MAX_PARAM_COUNT - 1 - ParamOffset); >=20 > + } else { >=20 > + Walker =3D RemoteFilePath + StrLen (RemoteFilePath); >=20 > + while ((--Walker) >=3D RemoteFilePath) { >=20 > + if ((*Walker =3D=3D L'\\') || >=20 > + (*Walker =3D=3D L'/' ) ) { It is better to remove the useless space in the above line at the end of 'i= f' condition. >=20 > + break; >=20 > + } >=20 > + } >=20 > + >=20 > + mLocalFilePath =3D Walker + 1; >=20 > + } >=20 > + >=20 > + if (!StrLen (mLocalFilePath)) { >=20 > + mLocalFilePath =3D DEFAULT_HTML_FILE; >=20 > + } >=20 > + >=20 > + InitialSize =3D 0; >=20 > + Context.URI =3D StrnCatGrow ( >=20 > + &Context.URI, >=20 > + &InitialSize, >=20 > + RemoteFilePath, >=20 > + StrLen (RemoteFilePath) >=20 > + ); >=20 > + if (!Context.URI) { >=20 > + Status =3D EFI_OUT_OF_RESOURCES; >=20 > + goto Error; >=20 > + } >=20 > + >=20 > + // >=20 > + // Get the name of the Network Interface Card to be used if any. >=20 > + // >=20 > + UserNicName =3D ShellCommandLineGetValue (CheckPackage, L"-i"); >=20 > + >=20 > + ValueStr =3D ShellCommandLineGetValue (CheckPackage, L"-l"); >=20 > + if (ValueStr !=3D NULL) { >=20 > + if (!StringToUint16 ( >=20 > + ValueStr, >=20 > + &HttpConfigData.AccessPoint.IPv4Node->LocalPort >=20 > + ) >=20 > + ) { I suggest to align the end ')' of StringToUint16 to align with the paramete= rs. And the end ')' of 'if' to go right next to the end ')' of StringToUint= 16. >=20 > + goto Error; >=20 > + } >=20 > + } >=20 > + >=20 > + Context.BufferSize =3D DEFAULT_BUF_SIZE; >=20 > + >=20 > + ValueStr =3D ShellCommandLineGetValue (CheckPackage, L"-s"); >=20 > + if (ValueStr !=3D NULL) { >=20 > + Context.BufferSize =3D ShellStrToUintn (ValueStr); >=20 > + if (!Context.BufferSize || Context.BufferSize > MAX_BUF_SIZE) { >=20 > + ShellPrintHiiEx ( >=20 > + -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), >=20 > + mHttpHiiHandle, HTTP_APP_NAME, ValueStr >=20 > + ); >=20 > + goto Error; >=20 > + } >=20 > + } >=20 > + >=20 > + ValueStr =3D ShellCommandLineGetValue (CheckPackage, L"-t"); >=20 > + if (ValueStr !=3D NULL) { >=20 > + HttpConfigData.TimeOutMillisec =3D (UINT32)ShellStrToUintn (ValueStr= ); I am not sure if it is fine to transfer '-1' as time out value when the -t = with invalid number string. It depends on the NetworkPkg maintainers' revie= w. I am OK with other part of the patch. But I still need NetworkPkg maintaine= rs' help to review above issue and the implementation. There is no need to resend another patch if NetworkPkg maintainers are OK w= ith above issue and the implementation. Thanks, Zhichao >=20 > + } >=20 > + >=20 > + // >=20 > + // Locate all HTTP Service Binding protocols >=20 > + // >=20 > + Status =3D gBS->LocateHandleBuffer ( >=20 > + ByProtocol, >=20 > + &gEfiManagedNetworkServiceBindingProtocolGuid, >=20 > + NULL, >=20 > + &HandleCount, >=20 > + &Handles >=20 > + ); >=20 > + if (EFI_ERROR (Status) || (HandleCount =3D=3D 0)) { >=20 > + ShellPrintHiiEx ( >=20 > + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_NO_NIC), mHttpHiiHandle >=20 > + ); >=20 > + if (!EFI_ERROR (Status)) { >=20 > + Status =3D EFI_NOT_FOUND; >=20 > + } >=20 > + >=20 > + goto Error; >=20 > + } >=20 > + >=20 > + Status =3D EFI_NOT_FOUND; >=20 > + >=20 > + for (NicNumber =3D 0; >=20 > + (NicNumber < HandleCount) && (Status !=3D EFI_SUCCESS); >=20 > + NicNumber++) { >=20 > + ControllerHandle =3D Handles[NicNumber]; >=20 > + >=20 > + Status =3D GetNicName (ControllerHandle, NicNumber, NicName); >=20 > + if (EFI_ERROR (Status)) { >=20 > + ShellPrintHiiEx ( >=20 > + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_NIC_NAME), >=20 > + mHttpHiiHandle, NicNumber, Status >=20 > + ); >=20 > + continue; >=20 > + } >=20 > + >=20 > + if (UserNicName !=3D NULL) { >=20 > + if (StrCmp (NicName, UserNicName) !=3D 0) { >=20 > + Status =3D EFI_NOT_FOUND; >=20 > + continue; >=20 > + } >=20 > + NicFound =3D TRUE; >=20 > + } >=20 > + >=20 > + Status =3D CreateServiceChildAndOpenProtocol ( >=20 > + ControllerHandle, >=20 > + &gEfiHttpServiceBindingProtocolGuid, >=20 > + &gEfiHttpProtocolGuid, >=20 > + &HttpChildHandle, >=20 > + (VOID**)&Context.Http >=20 > + ); >=20 > + if (EFI_ERROR (Status)) { >=20 > + ShellPrintHiiEx ( >=20 > + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_OPEN_PROTOCOL), >=20 > + mHttpHiiHandle, NicName, Status >=20 > + ); >=20 > + continue; >=20 > + } >=20 > + >=20 > + Status =3D Context.Http->Configure (Context.Http, &HttpConfigData); >=20 > + if (EFI_ERROR (Status)) { >=20 > + ShellPrintHiiEx ( >=20 > + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_CONFIGURE), >=20 > + mHttpHiiHandle, NicName, Status >=20 > + ); >=20 > + continue; >=20 > + } >=20 > + >=20 > + Context.Flags =3D 0; >=20 > + if (ShellCommandLineGetFlag (CheckPackage, L"-m")) { >=20 > + Context.Flags |=3D DL_FLAG_TIME; >=20 > + } >=20 > + >=20 > + if (ShellCommandLineGetFlag (CheckPackage, L"-k")) { >=20 > + Context.Flags |=3D DL_FLAG_KEEP_BAD; >=20 > + } >=20 > + >=20 > + Status =3D DownloadFile (&Context); >=20 > + >=20 > + ShellPrintHiiEx ( >=20 > + -1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF), mHttpHiiHandle >=20 > + ); >=20 > + >=20 > + CloseProtocolAndDestroyServiceChild ( >=20 > + ControllerHandle, >=20 > + &gEfiHttpServiceBindingProtocolGuid, >=20 > + &gEfiHttpProtocolGuid, >=20 > + HttpChildHandle >=20 > + ); >=20 > + >=20 > + if (EFI_ERROR (Status)) { >=20 > + ShellPrintHiiEx ( >=20 > + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_DOWNLOAD), >=20 > + mHttpHiiHandle, RemoteFilePath, NicName, Status >=20 > + ); >=20 > + // If a user aborted the operation, do not try another controller. >=20 > + if (Status =3D=3D EFI_ABORTED) { >=20 > + goto Error; >=20 > + } >=20 > + } >=20 > + >=20 > + if (gHttpError) { >=20 > + // >=20 > + // This is not related to connection, so no need to repeat with >=20 > + // another interface. >=20 > + // >=20 > + break; >=20 > + } >=20 > + } >=20 > + >=20 > + if ((UserNicName !=3D NULL) && (!NicFound)) { >=20 > + ShellPrintHiiEx ( >=20 > + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_NIC_NOT_FOUND), >=20 > + mHttpHiiHandle, UserNicName >=20 > + ); >=20 > + } >=20 > + >=20 > +Error: >=20 > + ShellCommandLineFreeVarList (CheckPackage); >=20 > + SHELL_FREE_NON_NULL (Handles); >=20 > + SHELL_FREE_NON_NULL (Context.ServerAddrAndProto); >=20 > + SHELL_FREE_NON_NULL (Context.URI); >=20 > + >=20 > + return Status & ~MAX_BIT; >=20 > +} >=20 > + >=20 > +/** >=20 > + Check and convert the UINT16 option values of the 'http' command >=20 > + >=20 > + @param[in] ValueStr Value as an Unicode encoded string >=20 > + @param[out] Value UINT16 value >=20 > + >=20 > + @return TRUE The value was returned. >=20 > + @return FALSE A parsing error occured. >=20 > +**/ >=20 > +STATIC >=20 > +BOOLEAN >=20 > +StringToUint16 ( >=20 > + IN CONST CHAR16 *ValueStr, >=20 > + OUT UINT16 *Value >=20 > + ) >=20 > +{ >=20 > + UINTN Val; >=20 > + >=20 > + Val =3D ShellStrToUintn (ValueStr); >=20 > + if (Val > MAX_UINT16) { >=20 > + ShellPrintHiiEx ( >=20 > + -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), >=20 > + mHttpHiiHandle, HTTP_APP_NAME, ValueStr >=20 > + ); >=20 > + return FALSE; >=20 > + } >=20 > + >=20 > + *Value =3D (UINT16)Val; >=20 > + return TRUE; >=20 > +} >=20 > + >=20 > +/** >=20 > + Get the name of the NIC. >=20 > + >=20 > + @param[in] ControllerHandle The network physical device handle. >=20 > + @param[in] NicNumber The network physical device number. >=20 > + @param[out] NicName Address where to store the NIC name. >=20 > + The memory area has to be at least >=20 > + IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH >=20 > + double byte wide. >=20 > + >=20 > + @return EFI_SUCCESS The name of the NIC was returned. >=20 > + @return Others The creation of the child for the Managed >=20 > + Network Service failed or the opening of >=20 > + the Managed Network Protocol failed or >=20 > + the operational parameters for the >=20 > + Managed Network Protocol could not be >=20 > + read. >=20 > +**/ >=20 > +STATIC >=20 > +EFI_STATUS >=20 > +GetNicName ( >=20 > + IN EFI_HANDLE ControllerHandle, >=20 > + IN UINTN NicNumber, >=20 > + OUT CHAR16 *NicName >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + EFI_HANDLE MnpHandle; >=20 > + EFI_MANAGED_NETWORK_PROTOCOL *Mnp; >=20 > + EFI_SIMPLE_NETWORK_MODE SnpMode; >=20 > + >=20 > + Status =3D CreateServiceChildAndOpenProtocol ( >=20 > + ControllerHandle, >=20 > + &gEfiManagedNetworkServiceBindingProtocolGuid, >=20 > + &gEfiManagedNetworkProtocolGuid, >=20 > + &MnpHandle, >=20 > + (VOID**)&Mnp >=20 > + ); >=20 > + if (EFI_ERROR (Status)) { >=20 > + goto Error; >=20 > + } >=20 > + >=20 > + Status =3D Mnp->GetModeData (Mnp, NULL, &SnpMode); >=20 > + if (EFI_ERROR (Status) && (Status !=3D EFI_NOT_STARTED)) { >=20 > + goto Error; >=20 > + } >=20 > + >=20 > + UnicodeSPrint ( >=20 > + NicName, >=20 > + IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH, >=20 > + SnpMode.IfType =3D=3D NET_IFTYPE_ETHERNET ? >=20 > + L"eth%d" : >=20 > + L"unk%d", >=20 > + NicNumber >=20 > + ); >=20 > + >=20 > + Status =3D EFI_SUCCESS; >=20 > + >=20 > +Error: >=20 > + >=20 > + if (MnpHandle !=3D NULL) { >=20 > + CloseProtocolAndDestroyServiceChild ( >=20 > + ControllerHandle, >=20 > + &gEfiManagedNetworkServiceBindingProtocolGuid, >=20 > + &gEfiManagedNetworkProtocolGuid, >=20 > + MnpHandle >=20 > + ); >=20 > + } >=20 > + >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + Create a child for the service identified by its service binding proto= col GUID >=20 > + and get from the child the interface of the protocol identified by its= GUID. >=20 > + >=20 > + @param[in] ControllerHandle Controller handle. >=20 > + @param[in] ServiceBindingProtocolGuid Service binding protocol GUID= of the >=20 > + service to be created. >=20 > + @param[in] ProtocolGuid GUID of the protocol to be op= en. >=20 > + @param[out] ChildHandle Address where the handler of = the >=20 > + created child is returned. NU= LL is >=20 > + returned in case of error. >=20 > + @param[out] Interface Address where a pointer to th= e >=20 > + protocol interface is returne= d in >=20 > + case of success. >=20 > + >=20 > + @return EFI_SUCCESS The child was created and the protocol opened. >=20 > + @return Others Either the creation of the child or the opening >=20 > + of the protocol failed. >=20 > +**/ >=20 > +STATIC >=20 > +EFI_STATUS >=20 > +CreateServiceChildAndOpenProtocol ( >=20 > + IN EFI_HANDLE ControllerHandle, >=20 > + IN EFI_GUID *ServiceBindingProtocolGuid, >=20 > + IN EFI_GUID *ProtocolGuid, >=20 > + OUT EFI_HANDLE *ChildHandle, >=20 > + OUT VOID **Interface >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + >=20 > + *ChildHandle =3D NULL; >=20 > + Status =3D NetLibCreateServiceChild ( >=20 > + ControllerHandle, >=20 > + gImageHandle, >=20 > + ServiceBindingProtocolGuid, >=20 > + ChildHandle >=20 > + ); >=20 > + if (!EFI_ERROR (Status)) { >=20 > + Status =3D gBS->OpenProtocol ( >=20 > + *ChildHandle, >=20 > + ProtocolGuid, >=20 > + Interface, >=20 > + gImageHandle, >=20 > + ControllerHandle, >=20 > + EFI_OPEN_PROTOCOL_GET_PROTOCOL >=20 > + ); >=20 > + if (EFI_ERROR (Status)) { >=20 > + NetLibDestroyServiceChild ( >=20 > + ControllerHandle, >=20 > + gImageHandle, >=20 > + ServiceBindingProtocolGuid, >=20 > + *ChildHandle >=20 > + ); >=20 > + *ChildHandle =3D NULL; >=20 > + } >=20 > + } >=20 > + >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + Close the protocol identified by its GUID on the child handle of the s= ervice >=20 > + identified by its service binding protocol GUID, then destroy the chil= d >=20 > + handle. >=20 > + >=20 > + @param[in] ControllerHandle Controller handle. >=20 > + @param[in] ServiceBindingProtocolGuid Service binding protocol GUID = of the >=20 > + service to be destroyed. >=20 > + @param[in] ProtocolGuid GUID of the protocol to be clo= sed. >=20 > + @param[in] ChildHandle Handle of the child to be dest= royed. >=20 > + >=20 > +**/ >=20 > +STATIC >=20 > +VOID >=20 > +CloseProtocolAndDestroyServiceChild ( >=20 > + IN EFI_HANDLE ControllerHandle, >=20 > + IN EFI_GUID *ServiceBindingProtocolGuid, >=20 > + IN EFI_GUID *ProtocolGuid, >=20 > + IN EFI_HANDLE ChildHandle >=20 > + ) >=20 > +{ >=20 > + gBS->CloseProtocol ( >=20 > + ChildHandle, >=20 > + ProtocolGuid, >=20 > + gImageHandle, >=20 > + ControllerHandle >=20 > + ); >=20 > + >=20 > + NetLibDestroyServiceChild ( >=20 > + ControllerHandle, >=20 > + gImageHandle, >=20 > + ServiceBindingProtocolGuid, >=20 > + ChildHandle >=20 > + ); >=20 > +} >=20 > + >=20 > +/** >=20 > + Wait until operation completes. Completion is indicated by >=20 > + setting of an appropriate variable. >=20 > + >=20 > + @param[in] Context A pointer to the HTTP download contex= t. >=20 > + @param[in] CallBackComplete A pointer to the callback completion >=20 > + variable set by the callback. >=20 > + >=20 > + @return EFI_SUCCESS Callback signalled completion. >=20 > + @return EFI_TIMEOUT Timed out waiting for completion. >=20 > + @return Others Error waiting for completion. >=20 > +**/ >=20 > +STATIC >=20 > +EFI_STATUS >=20 > +WaitForCompletion ( >=20 > + IN DOWNLOAD_CONTEXT *Context, >=20 > + IN OUT BOOLEAN *CallBackComplete >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + EFI_EVENT WaitEvt; >=20 > + >=20 > + Status =3D EFI_SUCCESS; >=20 > + >=20 > + // Use a timer to measure timeout. Cannot use Stall here! >=20 > + Status =3D gBS->CreateEvent ( >=20 > + EVT_TIMER, >=20 > + TPL_CALLBACK, >=20 > + NULL, >=20 > + NULL, >=20 > + &WaitEvt >=20 > + ); >=20 > + ASSERT_EFI_ERROR (Status); >=20 > + >=20 > + if (!EFI_ERROR (Status)) { >=20 > + Status =3D gBS->SetTimer( >=20 > + WaitEvt, >=20 > + TimerRelative, >=20 > + EFI_TIMER_PERIOD_SECONDS (TIMER_MAX_TIMEOUT_S) >=20 > + ); >=20 > + >=20 > + ASSERT_EFI_ERROR (Status); >=20 > + } >=20 > + >=20 > + while (! *CallBackComplete && >=20 > + (!EFI_ERROR (Status)) && >=20 > + EFI_ERROR (gBS->CheckEvent (WaitEvt)) >=20 > + ) { >=20 > + Status =3D Context->Http->Poll (Context->Http); >=20 > + } >=20 > + >=20 > + gBS->SetTimer (WaitEvt, TimerCancel, 0); >=20 > + gBS->CloseEvent (WaitEvt); >=20 > + >=20 > + if (*CallBackComplete) { >=20 > + return EFI_SUCCESS; >=20 > + } >=20 > + >=20 > + if (!EFI_ERROR (Status)) { >=20 > + Status =3D EFI_TIMEOUT; >=20 > + } >=20 > + >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + Generate and send a request to the http server. >=20 > + >=20 > + @param[in] Context HTTP download context. >=20 > + @param[in] DownloadUrl Fully qualified URL to be downloaded. >=20 > + >=20 > + @return EFI_SUCCESS Request has been sent successfully. >=20 > + @return EFI_INVALID_PARAMETER Invalid URL. >=20 > + @return EFI_OUT_OF_RESOURCES Out of memory. >=20 > + @return EFI_DEVICE_ERROR If HTTPS is used, this probably >=20 > + means that TLS support either was not >=20 > + installed or not configured. >=20 > + @return Others Error sending the request. >=20 > +**/ >=20 > + >=20 > +STATIC >=20 > +EFI_STATUS >=20 > +SendRequest ( >=20 > + IN DOWNLOAD_CONTEXT *Context, >=20 > + IN CHAR16 *DownloadUrl >=20 > + ) >=20 > +{ >=20 > + EFI_HTTP_REQUEST_DATA RequestData; >=20 > + EFI_HTTP_HEADER RequestHeader; >=20 > + EFI_HTTP_MESSAGE RequestMessage; >=20 > + EFI_STATUS Status; >=20 > + CHAR16 *Host; >=20 > + UINTN StringSize; >=20 > + >=20 > + ZeroMem (&RequestData, sizeof (RequestData)); >=20 > + ZeroMem (&RequestHeader, sizeof (RequestHeader)); >=20 > + ZeroMem (&RequestMessage, sizeof (RequestMessage)); >=20 > + ZeroMem (&Context->RequestToken, sizeof (Context->RequestToken)); >=20 > + >=20 > + RequestHeader.FieldName =3D "Host"; >=20 > + >=20 > + Host =3D (CHAR16 *)Context->ServerAddrAndProto; >=20 > + while (*Host !=3D CHAR_NULL && *Host !=3D L'/') { >=20 > + Host++; >=20 > + } >=20 > + >=20 > + if (*Host =3D=3D CHAR_NULL) { >=20 > + return EFI_INVALID_PARAMETER; >=20 > + } >=20 > + >=20 > + // >=20 > + // Get the next slash >=20 > + // >=20 > + Host++; >=20 > + // >=20 > + // And now the host name >=20 > + // >=20 > + Host++; >=20 > + >=20 > + StringSize =3D StrLen (Host) + 1; >=20 > + RequestHeader.FieldValue =3D AllocatePool (StringSize); >=20 > + if (!RequestHeader.FieldValue) { >=20 > + return EFI_OUT_OF_RESOURCES; >=20 > + } >=20 > + >=20 > + UnicodeStrToAsciiStrS (Host, RequestHeader.FieldValue, StringSize); >=20 > + >=20 > + RequestMessage.HeaderCount++; >=20 > + >=20 > + RequestData.Method =3D HttpMethodGet; >=20 > + RequestData.Url =3D DownloadUrl; >=20 > + >=20 > + RequestMessage.Data.Request =3D &RequestData; >=20 > + RequestMessage.Headers =3D &RequestHeader; >=20 > + RequestMessage.BodyLength =3D 0; >=20 > + RequestMessage.Body =3D NULL; >=20 > + Context->RequestToken.Event =3D NULL; >=20 > + >=20 > + // >=20 > + // Completion callback event to be set when Request completes. >=20 > + // >=20 > + Status =3D gBS->CreateEvent ( >=20 > + EVT_NOTIFY_SIGNAL, >=20 > + TPL_CALLBACK, >=20 > + RequestCallback, >=20 > + Context, >=20 > + &Context->RequestToken.Event >=20 > + ); >=20 > + ASSERT_EFI_ERROR (Status); >=20 > + >=20 > + Context->RequestToken.Status =3D EFI_SUCCESS; >=20 > + Context->RequestToken.Message =3D &RequestMessage; >=20 > + gRequestCallbackComplete =3D FALSE; >=20 > + Status =3D Context->Http->Request (Context->Http, &Context->RequestT= oken); >=20 > + if (EFI_ERROR (Status)) { >=20 > + goto Error; >=20 > + } >=20 > + >=20 > + Status =3D WaitForCompletion (Context, &gRequestCallbackComplete); >=20 > + if (EFI_ERROR (Status)) { >=20 > + Context->Http->Cancel (Context->Http, &Context->RequestToken); >=20 > + } >=20 > +Error: >=20 > + SHELL_FREE_NON_NULL (RequestHeader.FieldValue); >=20 > + if (Context->RequestToken.Event) { >=20 > + gBS->CloseEvent (Context->RequestToken.Event); >=20 > + ZeroMem (&Context->RequestToken, sizeof (Context->RequestToken)); >=20 > + } >=20 > + >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + Update the progress of a file download >=20 > + This procedure is called each time a new HTTP body portion is received= . >=20 > + >=20 > + @param[in] Context HTTP download context. >=20 > + @param[in] DownloadLen Portion size, in bytes. >=20 > + @param[in] Buffer The pointer to the parsed buffer. >=20 > + >=20 > + @retval EFI_SUCCESS Portion saved. >=20 > + @retval Other Error saving the portion. >=20 > + >=20 > +**/ >=20 > +STATIC >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +SavePortion ( >=20 > + IN DOWNLOAD_CONTEXT *Context, >=20 > + IN UINTN DownloadLen, >=20 > + IN CHAR8 *Buffer >=20 > + ) >=20 > +{ >=20 > + CHAR16 Progress[HTTP_PROGRESS_MESSAGE_SIZE]; >=20 > + UINTN NbOfKb; >=20 > + UINTN Index; >=20 > + UINTN LastStep; >=20 > + UINTN Step; >=20 > + EFI_STATUS Status; >=20 > + >=20 > + LastStep =3D 0; >=20 > + Step =3D 0; >=20 > + ShellSetFilePosition (mFileHandle, Context->LastReportedNbOfBytes); >=20 > + Status =3D ShellWriteFile (mFileHandle, &DownloadLen, Buffer); >=20 > + if (EFI_ERROR (Status)) { >=20 > + if (Context->ContentDownloaded > 0) { >=20 > + ShellPrintHiiEx ( >=20 > + -1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF), mHttpHiiHandle >=20 > + ); >=20 > + } >=20 > + >=20 > + ShellPrintHiiEx ( >=20 > + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_WRITE), >=20 > + mHttpHiiHandle, mLocalFilePath, Status >=20 > + ); >=20 > + >=20 > + return Status; >=20 > + } >=20 > + >=20 > + if (Context->ContentDownloaded =3D=3D 0) { >=20 > + ShellPrintEx (-1, -1, L"%s 0 Kb", HTTP_PROGR_FRAME); >=20 > + } >=20 > + >=20 > + Context->ContentDownloaded +=3D DownloadLen; >=20 > + NbOfKb =3D Context->ContentDownloaded >> 10; >=20 > + >=20 > + Progress[0] =3D L'\0'; >=20 > + if (Context->ContentLength) { >=20 > + LastStep =3D (Context->LastReportedNbOfBytes * > HTTP_PROGRESS_SLIDER_STEPS) / >=20 > + Context->ContentLength; >=20 > + Step =3D (Context->ContentDownloaded * HTTP_PROGRESS_SLIDER_STE= PS) / >=20 > + Context->ContentLength; >=20 > + } >=20 > + >=20 > + Context->LastReportedNbOfBytes =3D Context->ContentDownloaded; >=20 > + >=20 > + if (Step <=3D LastStep) { >=20 > + if (!Context->ContentLength) { >=20 > + // >=20 > + // Update downloaded size, there is no length info available. >=20 > + // >=20 > + ShellPrintEx (-1, -1, L"%s", HTTP_KB); >=20 > + ShellPrintEx (-1, -1, L"%7d Kb", NbOfKb); >=20 > + } >=20 > + >=20 > + return EFI_SUCCESS; >=20 > + } >=20 > + >=20 > + ShellPrintEx (-1, -1, L"%s", HTTP_PROGRESS_DEL); >=20 > + >=20 > + Status =3D StrCpyS (Progress, HTTP_PROGRESS_MESSAGE_SIZE, > HTTP_PROGR_FRAME); >=20 > + if (EFI_ERROR (Status)) { >=20 > + return Status; >=20 > + } >=20 > + >=20 > + for (Index =3D 1; Index < Step; Index++) { >=20 > + Progress[Index] =3D L'=3D'; >=20 > + } >=20 > + >=20 > + if (Step) { >=20 > + Progress[Step] =3D L'>'; >=20 > + } >=20 > + >=20 > + UnicodeSPrint ( >=20 > + Progress + (sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) - 1, >=20 > + sizeof (Progress) - sizeof (HTTP_PROGR_FRAME), >=20 > + L" %7d Kb", >=20 > + NbOfKb >=20 > + ); >=20 > + >=20 > + >=20 > + ShellPrintEx (-1, -1, L"%s", Progress); >=20 > + >=20 > + return EFI_SUCCESS; >=20 > +} >=20 > + >=20 > +/** >=20 > + Replace the original Host and URI with Host and URI returned by the >=20 > + HTTP server in 'Location' header (redirection). >=20 > + >=20 > + @param[in] Location A pointer to the 'Location' string >=20 > + provided by HTTP server. >=20 > + @param[in] Context A pointer to HTTP download context. >=20 > + @param[in] DownloadUrl Fully qualified HTTP URL. >=20 > + >=20 > + @return EFI_SUCCESS Host and URI were successfully set. >=20 > + @return EFI_OUT_OF_RESOURCES Error setting Host or URI. >=20 > +**/ >=20 > + >=20 > +STATIC >=20 > +EFI_STATUS >=20 > +SetHostURI ( >=20 > + IN CHAR8 *Location, >=20 > + IN DOWNLOAD_CONTEXT *Context, >=20 > + IN CHAR16 *DownloadUrl >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + UINTN StringSize; >=20 > + UINTN FirstStep; >=20 > + UINTN Idx; >=20 > + UINTN Step; >=20 > + CHAR8 *Walker; >=20 > + CHAR16 *Temp; >=20 > + CHAR8 *Tmp; >=20 > + CHAR16 *Url; >=20 > + BOOLEAN IsAbEmptyUrl; >=20 > + >=20 > + Tmp =3D NULL; >=20 > + Url =3D NULL; >=20 > + IsAbEmptyUrl =3D FALSE; >=20 > + FirstStep =3D 0; >=20 > + >=20 > + StringSize =3D (AsciiStrSize (Location) * sizeof (CHAR16)); >=20 > + Url =3D AllocateZeroPool (StringSize); >=20 > + if (!Url) { >=20 > + return EFI_OUT_OF_RESOURCES; >=20 > + } >=20 > + >=20 > + Status =3D AsciiStrToUnicodeStrS ( >=20 > + (CONST CHAR8 *)Location, >=20 > + Url, >=20 > + StringSize >=20 > + ); >=20 > + >=20 > + if (EFI_ERROR (Status)) { >=20 > + goto Error; >=20 > + } >=20 > + >=20 > + // >=20 > + // If an HTTP server redirects to the same location more than once, >=20 > + // then stop attempts and tell it is not reachable. >=20 > + // >=20 > + if (!StrCmp (Url, DownloadUrl)) { >=20 > + Status =3D EFI_NO_MAPPING; >=20 > + goto Error; >=20 > + } >=20 > + >=20 > + if (AsciiStrLen (Location) > 2) { >=20 > + // Some servers return 'Location: //server/resource' >=20 > + IsAbEmptyUrl =3D (Location[0] =3D=3D '/') && (Location[1] =3D=3D '/'= ); >=20 > + if (IsAbEmptyUrl) { >=20 > + // Skip first "//" >=20 > + Location +=3D 2; >=20 > + FirstStep =3D 1; >=20 > + } >=20 > + } >=20 > + >=20 > + if (AsciiStrStr (Location, "://") || IsAbEmptyUrl) { >=20 > + Idx =3D 0; >=20 > + Walker =3D Location; >=20 > + >=20 > + for (Step =3D FirstStep; Step < 2; Step++) { >=20 > + for (; *Walker !=3D '/' && *Walker !=3D '\0'; Walker++) { >=20 > + Idx++; >=20 > + } >=20 > + if (!Step) { >=20 > + // >=20 > + // Skip "//" >=20 > + // >=20 > + Idx +=3D 2; >=20 > + Walker +=3D 2; >=20 > + } >=20 > + } >=20 > + >=20 > + Tmp =3D AllocateZeroPool (Idx + 1); >=20 > + if (!Tmp) { >=20 > + Status =3D EFI_OUT_OF_RESOURCES; >=20 > + goto Error; >=20 > + } >=20 > + >=20 > + CopyMem (Tmp, Location, Idx); >=20 > + >=20 > + // >=20 > + // Location now points to URI >=20 > + // >=20 > + Location +=3D Idx; >=20 > + StringSize =3D (Idx + 1) * sizeof (CHAR16); >=20 > + >=20 > + SHELL_FREE_NON_NULL (Context->ServerAddrAndProto); >=20 > + >=20 > + Temp =3D AllocateZeroPool (StringSize); >=20 > + if (!Temp) { >=20 > + Status =3D EFI_OUT_OF_RESOURCES; >=20 > + goto Error; >=20 > + } >=20 > + >=20 > + Status =3D AsciiStrToUnicodeStrS ( >=20 > + (CONST CHAR8 *)Tmp, >=20 > + Temp, >=20 > + StringSize >=20 > + ); >=20 > + if (EFI_ERROR (Status)) { >=20 > + SHELL_FREE_NON_NULL (Temp); >=20 > + goto Error; >=20 > + } >=20 > + >=20 > + Idx =3D 0; >=20 > + if (IsAbEmptyUrl) { >=20 > + Context->ServerAddrAndProto =3D StrnCatGrow ( >=20 > + &Context->ServerAddrAndProto, >=20 > + &Idx, >=20 > + L"http://", >=20 > + StrLen (L"http://") >=20 > + ); >=20 > + } >=20 > + >=20 > + Context->ServerAddrAndProto =3D StrnCatGrow ( >=20 > + &Context->ServerAddrAndProto, >=20 > + &Idx, >=20 > + Temp, >=20 > + StrLen (Temp) >=20 > + ); >=20 > + SHELL_FREE_NON_NULL (Temp); >=20 > + if (!Context->ServerAddrAndProto) { >=20 > + Status =3D EFI_OUT_OF_RESOURCES; >=20 > + goto Error; >=20 > + } >=20 > + } >=20 > + >=20 > + SHELL_FREE_NON_NULL (Context->URI); >=20 > + >=20 > + StringSize =3D AsciiStrSize (Location) * sizeof (CHAR16); >=20 > + Context->URI =3D AllocateZeroPool (StringSize); >=20 > + if (!Context->URI) { >=20 > + Status =3D EFI_OUT_OF_RESOURCES; >=20 > + goto Error; >=20 > + } >=20 > + >=20 > + // >=20 > + // Now make changes to the URI part. >=20 > + // >=20 > + Status =3D AsciiStrToUnicodeStrS ( >=20 > + (CONST CHAR8 *)Location, >=20 > + Context->URI, >=20 > + StringSize >=20 > + ); >=20 > +Error: >=20 > + SHELL_FREE_NON_NULL (Tmp); >=20 > + SHELL_FREE_NON_NULL (Url); >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + Message parser callback. >=20 > + Save a portion of HTTP body. >=20 > + >=20 > + @param[in] EventType Type of event. Can be either >=20 > + OnComplete or OnData. >=20 > + @param[in] Data A pointer to the buffer with data. >=20 > + @param[in] Length Data length of this portion. >=20 > + @param[in] Context A pointer to the HTTP download context. >=20 > + >=20 > + @return EFI_SUCCESS The portion was processed successfully. >=20 > + @return Other Error returned by SavePortion. >=20 > +**/ >=20 > + >=20 > +STATIC >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +ParseMsg ( >=20 > + IN HTTP_BODY_PARSE_EVENT EventType, >=20 > + IN CHAR8 *Data, >=20 > + IN UINTN Length, >=20 > + IN VOID *Context >=20 > + ) >=20 > +{ >=20 > + if (!Data || (EventType =3D=3D BodyParseEventOnComplete) || !Context) = { >=20 > + return EFI_SUCCESS; >=20 > + } >=20 > + >=20 > + return SavePortion (Context, Length, Data); >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + Get HTTP server response and collect the whole body as a file. >=20 > + Set appropriate status in Context (REQ_OK, REQ_REPEAT, REQ_ERROR). >=20 > + Note that even if HTTP server returns an error code, it might send >=20 > + the body as well. This body will be collected in the resultant file. >=20 > + >=20 > + @param[in] Context A pointer to the HTTP download context. >=20 > + @param[in] DownloadedUrl A pointer to the fully qualified URL to d= ownload. >=20 > + >=20 > + @return EFI_SUCCESS Valid file. Body successfully collected. >=20 > + @return EFI_HTTP_ERROR Response is a valid HTTP response, but th= e >=20 > + HTTP server >=20 > + indicated an error (HTTP code >=3D 400). >=20 > + Response body MAY contain full >=20 > + HTTP server response. >=20 > + @return Others Error getting the reponse from the HTTP s= erver. >=20 > + Response body is not collected. >=20 > +**/ >=20 > +STATIC >=20 > +EFI_STATUS >=20 > +GetResponse ( >=20 > + IN DOWNLOAD_CONTEXT *Context, >=20 > + IN CHAR16 *DownloadUrl >=20 > + ) >=20 > +{ >=20 > + EFI_HTTP_RESPONSE_DATA ResponseData; >=20 > + EFI_HTTP_MESSAGE ResponseMessage; >=20 > + EFI_HTTP_HEADER *Header; >=20 > + EFI_STATUS Status; >=20 > + VOID *MsgParser; >=20 > + CONST CHAR16 *Desc; >=20 > + BOOLEAN IsTrunked; >=20 > + BOOLEAN Redirection; >=20 > + >=20 > + ZeroMem (&ResponseData, sizeof (ResponseData)); >=20 > + ZeroMem (&ResponseMessage, sizeof (ResponseMessage)); >=20 > + ZeroMem (&Context->ResponseToken, sizeof (Context->ResponseToken)); >=20 > + IsTrunked =3D FALSE; >=20 > + >=20 > + ResponseMessage.Body =3D Context->Buffer; >=20 > + Context->ResponseToken.Status =3D EFI_SUCCESS; >=20 > + Context->ResponseToken.Message =3D &ResponseMessage; >=20 > + Context->ContentLength =3D 0; >=20 > + Context->Status =3D REQ_OK; >=20 > + MsgParser =3D NULL; >=20 > + ResponseData.StatusCode =3D HTTP_STATUS_UNSUPPORTED_STATUS; >=20 > + ResponseMessage.Data.Response =3D &ResponseData; >=20 > + Context->ResponseToken.Event =3D NULL; >=20 > + >=20 > + do { >=20 > + SHELL_FREE_NON_NULL (ResponseMessage.Headers); >=20 > + ResponseMessage.HeaderCount =3D 0; >=20 > + gResponseCallbackComplete =3D FALSE; >=20 > + ResponseMessage.BodyLength =3D Context->BufferSize; >=20 > + >=20 > + if (ShellGetExecutionBreakFlag ()) { >=20 > + Status =3D EFI_ABORTED; >=20 > + break; >=20 > + } >=20 > + >=20 > + if (!Context->ContentDownloaded && !Context->ResponseToken.Event) { >=20 > + Status =3D gBS->CreateEvent ( >=20 > + EVT_NOTIFY_SIGNAL, >=20 > + TPL_CALLBACK, >=20 > + ResponseCallback, >=20 > + Context, >=20 > + &Context->ResponseToken.Event >=20 > + ); >=20 > + ASSERT_EFI_ERROR (Status); >=20 > + } else { >=20 > + ResponseMessage.Data.Response =3D NULL; >=20 > + } >=20 > + >=20 > + if (EFI_ERROR (Status)) { >=20 > + break; >=20 > + } >=20 > + >=20 > + Status =3D Context->Http->Response (Context->Http, &Context- > >ResponseToken); >=20 > + if (EFI_ERROR (Status)) { >=20 > + break; >=20 > + } >=20 > + >=20 > + Status =3D WaitForCompletion (Context, &gResponseCallbackComplete); >=20 > + if (EFI_ERROR (Status) && ResponseMessage.HeaderCount) { >=20 > + Status =3D EFI_SUCCESS; >=20 > + } >=20 > + >=20 > + if (EFI_ERROR (Status)) { >=20 > + Context->Http->Cancel (Context->Http, &Context->ResponseToken); >=20 > + break; >=20 > + } >=20 > + >=20 > + if (!Context->ContentDownloaded) { >=20 > + Redirection =3D >=20 > + ((ResponseData.StatusCode >=3D HTTP_STATUS_300_MULTIPLE_CHOICES) > && >=20 > + (ResponseData.StatusCode <=3D > HTTP_STATUS_307_TEMPORARY_REDIRECT) >=20 > + ) || >=20 > + (ResponseData.StatusCode =3D=3D > HTTP_STATUS_308_PERMANENT_REDIRECT); >=20 > + >=20 > + if (Redirection) { >=20 > + // >=20 > + // Need to repeat the request with new Location (server redirect= ed). >=20 > + // >=20 > + Context->Status =3D REQ_NEED_REPEAT; >=20 > + >=20 > + Header =3D HttpFindHeader ( >=20 > + ResponseMessage.HeaderCount, >=20 > + ResponseMessage.Headers, >=20 > + "Location" >=20 > + ); >=20 > + if (Header) { >=20 > + Status =3D SetHostURI (Header->FieldValue, Context, DownloadUr= l); >=20 > + if (Status =3D=3D EFI_NO_MAPPING) { >=20 > + ShellPrintHiiEx ( >=20 > + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_STATUSCODE), >=20 > + mHttpHiiHandle, Context->ServerAddrAndProto, >=20 > + L"Recursive HTTP server relocation", >=20 > + Context->URI >=20 > + ); >=20 > + } >=20 > + } else { >=20 > + // >=20 > + // Bad reply from the server. Server must specify the location= . >=20 > + // Indicate that resource was not found, and no body collected= . >=20 > + // >=20 > + Status =3D EFI_NOT_FOUND; >=20 > + } >=20 > + >=20 > + Context->Http->Cancel (Context->Http, &Context->ResponseToken); >=20 > + break; >=20 > + } >=20 > + >=20 > + // >=20 > + // Init message-body parser by header information. >=20 > + // >=20 > + if (!MsgParser) { >=20 > + Status =3D HttpInitMsgParser ( >=20 > + ResponseMessage.Data.Request->Method, >=20 > + ResponseData.StatusCode, >=20 > + ResponseMessage.HeaderCount, >=20 > + ResponseMessage.Headers, >=20 > + ParseMsg, >=20 > + Context, >=20 > + &MsgParser >=20 > + ); >=20 > + if (EFI_ERROR (Status)) { >=20 > + break; >=20 > + } >=20 > + } >=20 > + >=20 > + // >=20 > + // If it is a trunked message, rely on the parser. >=20 > + // >=20 > + Header =3D HttpFindHeader ( >=20 > + ResponseMessage.HeaderCount, >=20 > + ResponseMessage.Headers, >=20 > + "Transfer-Encoding" >=20 > + ); >=20 > + IsTrunked =3D (Header && !AsciiStrCmp (Header->FieldValue, "chunke= d")); >=20 > + >=20 > + HttpGetEntityLength (MsgParser, &Context->ContentLength); >=20 > + >=20 > + if (ResponseData.StatusCode >=3D HTTP_STATUS_400_BAD_REQUEST && >=20 > + (ResponseData.StatusCode !=3D > HTTP_STATUS_308_PERMANENT_REDIRECT) >=20 > + ) { >=20 > + // >=20 > + // Server reported an error via Response code. >=20 > + // Collect the body if any. >=20 > + // >=20 > + if (!gHttpError) { >=20 > + gHttpError =3D TRUE; >=20 > + >=20 > + Desc =3D ErrStatusDesc[ResponseData.StatusCode - >=20 > + HTTP_STATUS_400_BAD_REQUEST]; >=20 > + ShellPrintHiiEx ( >=20 > + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_STATUSCODE), >=20 > + mHttpHiiHandle, Context->ServerAddrAndProto, >=20 > + Desc, >=20 > + Context->URI >=20 > + ); >=20 > + >=20 > + // >=20 > + // This gives an RFC HTTP error. >=20 > + // >=20 > + Context->Status =3D ShellStrToUintn (Desc); >=20 > + } >=20 > + } >=20 > + } >=20 > + >=20 > + // Do NOT try to parse an empty body. >=20 > + if (ResponseMessage.BodyLength || IsTrunked) { >=20 > + Status =3D HttpParseMessageBody ( >=20 > + MsgParser, >=20 > + ResponseMessage.BodyLength, >=20 > + ResponseMessage.Body >=20 > + ); >=20 > + } >=20 > + } while (!HttpIsMessageComplete (MsgParser) && >=20 > + !EFI_ERROR (Status) && >=20 > + ResponseMessage.BodyLength >=20 > + ); >=20 > + >=20 > + SHELL_FREE_NON_NULL (MsgParser); >=20 > + if (Context->ResponseToken.Event) { >=20 > + gBS->CloseEvent (Context->ResponseToken.Event); >=20 > + ZeroMem (&Context->ResponseToken, sizeof (Context->ResponseToken)); >=20 > + } >=20 > + >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + Worker function that downloads the data of a file from an HTTP server = given >=20 > + the path of the file and its size. >=20 > + >=20 > + @param[in] Context A pointer to the HTTP download context. >=20 > + >=20 > + @retval EFI_SUCCESS The file was downloaded. >=20 > + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. >=20 > + #retval EFI_HTTP_ERROR The server returned a valid HTTP error. >=20 > + Examine the mLocalFilePath file >=20 > + to get error body. >=20 > + @retval Others The downloading of the file from the se= rver >=20 > + failed. >=20 > + >=20 > +**/ >=20 > +STATIC >=20 > +EFI_STATUS >=20 > +DownloadFile ( >=20 > + IN DOWNLOAD_CONTEXT *Context >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + CHAR16 *DownloadUrl; >=20 > + UINTN UrlSize; >=20 > + >=20 > + ASSERT (Context); >=20 > + if (!Context) { >=20 > + return EFI_INVALID_PARAMETER; >=20 > + } >=20 > + >=20 > + DownloadUrl =3D NULL; >=20 > + >=20 > + Context->Buffer =3D AllocatePool (Context->BufferSize); >=20 > + if (!Context->Buffer) { >=20 > + Status =3D EFI_OUT_OF_RESOURCES; >=20 > + goto ON_EXIT; >=20 > + } >=20 > + >=20 > + // >=20 > + // OPEN FILE >=20 > + // >=20 > + if (!EFI_ERROR (ShellFileExists (mLocalFilePath))) { >=20 > + ShellDeleteFileByName (mLocalFilePath); >=20 > + } >=20 > + >=20 > + Status =3D ShellOpenFileByName ( >=20 > + mLocalFilePath, >=20 > + &mFileHandle, >=20 > + EFI_FILE_MODE_CREATE | >=20 > + EFI_FILE_MODE_WRITE | >=20 > + EFI_FILE_MODE_READ, >=20 > + 0); >=20 > + if (EFI_ERROR (Status)) { >=20 > + ShellPrintHiiEx ( >=20 > + -1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), >=20 > + mHttpHiiHandle, HTTP_APP_NAME, mLocalFilePath >=20 > + ); >=20 > + goto ON_EXIT; >=20 > + } >=20 > + >=20 > + do { >=20 > + SHELL_FREE_NON_NULL (DownloadUrl); >=20 > + UrlSize =3D 0; >=20 > + DownloadUrl =3D StrnCatGrow ( >=20 > + &DownloadUrl, >=20 > + &UrlSize, >=20 > + Context->ServerAddrAndProto, >=20 > + StrLen (Context->ServerAddrAndProto) >=20 > + ); >=20 > + if (Context->URI[0] !=3D L'/') { >=20 > + DownloadUrl =3D StrnCatGrow ( >=20 > + &DownloadUrl, >=20 > + &UrlSize, >=20 > + L"/", >=20 > + StrLen (Context->ServerAddrAndProto) >=20 > + ); >=20 > + } >=20 > + >=20 > + DownloadUrl =3D StrnCatGrow ( >=20 > + &DownloadUrl, >=20 > + &UrlSize, >=20 > + Context->URI, >=20 > + StrLen (Context->URI)); >=20 > + >=20 > + ShellPrintHiiEx ( >=20 > + -1, -1, NULL, STRING_TOKEN (STR_HTTP_DOWNLOADING), >=20 > + mHttpHiiHandle, DownloadUrl); >=20 > + >=20 > + Status =3D SendRequest (Context, DownloadUrl); >=20 > + if (Status) { >=20 > + goto ON_EXIT; >=20 > + } >=20 > + >=20 > + Status =3D GetResponse (Context, DownloadUrl); >=20 > + >=20 > + if (Status) { >=20 > + goto ON_EXIT; >=20 > + } >=20 > + >=20 > + } while (Context->Status =3D=3D REQ_NEED_REPEAT); >=20 > + >=20 > + if (Context->Status) { >=20 > + Status =3D ENCODE_ERROR (Context->Status); >=20 > + } >=20 > + >=20 > +ON_EXIT: >=20 > + // >=20 > + // CLOSE FILE >=20 > + // >=20 > + if (mFileHandle) { >=20 > + if (EFI_ERROR (Status) && !(Context->Flags & DL_FLAG_KEEP_BAD)) { >=20 > + ShellDeleteFile (&mFileHandle); >=20 > + } else { >=20 > + ShellCloseFile (&mFileHandle); >=20 > + } >=20 > + } >=20 > + >=20 > + SHELL_FREE_NON_NULL (DownloadUrl); >=20 > + SHELL_FREE_NON_NULL (Context->Buffer); >=20 > + >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + Retrive HII package list from ImageHandle and publish to HII database. >=20 > + >=20 > + @param ImageHandle The image handle of the process. >=20 > + >=20 > + @return HII handle. >=20 > +**/ >=20 > +EFI_HII_HANDLE >=20 > +InitializeHiiPackage ( >=20 > + EFI_HANDLE ImageHandle >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + EFI_HII_PACKAGE_LIST_HEADER *PackageList; >=20 > + EFI_HII_HANDLE HiiHandle; >=20 > + >=20 > + // >=20 > + // Retrieve HII package list from ImageHandle >=20 > + // >=20 > + Status =3D gBS->OpenProtocol ( >=20 > + ImageHandle, >=20 > + &gEfiHiiPackageListProtocolGuid, >=20 > + (VOID **)&PackageList, >=20 > + ImageHandle, >=20 > + NULL, >=20 > + EFI_OPEN_PROTOCOL_GET_PROTOCOL >=20 > + ); >=20 > + ASSERT_EFI_ERROR (Status); >=20 > + if (EFI_ERROR (Status)) { >=20 > + return NULL; >=20 > + } >=20 > + >=20 > + // >=20 > + // Publish HII package list to HII Database. >=20 > + // >=20 > + Status =3D gHiiDatabase->NewPackageList ( >=20 > + gHiiDatabase, >=20 > + PackageList, >=20 > + NULL, >=20 > + &HiiHandle >=20 > + ); >=20 > + ASSERT_EFI_ERROR (Status); >=20 > + if (EFI_ERROR (Status)) { >=20 > + return NULL; >=20 > + } >=20 > + >=20 > + return HiiHandle; >=20 > +} >=20 > diff --git a/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h > b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h > new file mode 100644 > index 000000000000..5c7b90e8cab4 > --- /dev/null > +++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h > @@ -0,0 +1,89 @@ > +/** @file >=20 > + Header file for 'http' command functions. >=20 > + >=20 > + Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved. >=20 > + Copyright (c) 2015, ARM Ltd. All rights reserved.
>=20 > + Copyright (c) 2020, Broadcom. All rights reserved.
>=20 > + >=20 > + SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > + >=20 > +**/ >=20 > + >=20 > +#ifndef _HTTP_H_ >=20 > +#define _HTTP_H_ >=20 > + >=20 > +#include >=20 > + >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > + >=20 > +#include >=20 > +#include >=20 > +#include >=20 > + >=20 > +#define HTTP_APP_NAME L"http" >=20 > + >=20 > +#define REQ_OK 0 >=20 > +#define REQ_NEED_REPEAT 1 >=20 > + >=20 > +// Download Flags >=20 > +#define DL_FLAG_TIME BIT0 // Show elapsed time. >=20 > +#define DL_FLAG_KEEP_BAD BIT1 // Keep files even if download failed. >=20 > + >=20 > +extern EFI_HII_HANDLE mHttpHiiHandle; >=20 > + >=20 > +typedef struct { >=20 > + UINTN ContentDownloaded; >=20 > + UINTN ContentLength; >=20 > + UINTN LastReportedNbOfBytes; >=20 > + UINTN BufferSize; >=20 > + UINTN Status; >=20 > + UINTN Flags; >=20 > + UINT8 *Buffer; >=20 > + CHAR16 *ServerAddrAndProto; >=20 > + CHAR16 *URI; >=20 > + EFI_HTTP_TOKEN ResponseToken; >=20 > + EFI_HTTP_TOKEN RequestToken; >=20 > + EFI_HTTP_PROTOCOL *Http; >=20 > +} DOWNLOAD_CONTEXT; >=20 > + >=20 > +/** >=20 > + Function for 'http' command. >=20 > + >=20 > + @param[in] ImageHandle The image handle. >=20 > + @param[in] SystemTable The system table. >=20 > + >=20 > + @retval SHELL_SUCCESS Command completed successfully. >=20 > + @retval SHELL_INVALID_PARAMETER Command usage error. >=20 > + @retval SHELL_ABORTED The user aborts the operation. >=20 > + @retval value Unknown error. >=20 > +**/ >=20 > +SHELL_STATUS >=20 > +RunHttp ( >=20 > + IN EFI_HANDLE ImageHandle, >=20 > + IN EFI_SYSTEM_TABLE *SystemTable >=20 > + ); >=20 > + >=20 > +/** >=20 > + Retrive HII package list from ImageHandle and publish to HII database. >=20 > + >=20 > + @param ImageHandle The image handle of the process. >=20 > + >=20 > + @return HII handle. >=20 > +**/ >=20 > +EFI_HII_HANDLE >=20 > +InitializeHiiPackage ( >=20 > + EFI_HANDLE ImageHandle >=20 > + ); >=20 > +#endif // _HTTP_H_ >=20 > 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 @@ > +// /** >=20 > +// >=20 > +// (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
>=20 > +// Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved. >=20 > +// Copyright (c) 2020, Broadcom. All rights reserved.
>=20 > +// SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > +// >=20 > +// Module Name: >=20 > +// >=20 > +// Http.uni >=20 > +// >=20 > +// Abstract: >=20 > +// >=20 > +// String definitions for UEFI Shell HTTP command >=20 > +// >=20 > +// >=20 > +// **/ >=20 > + >=20 > +/=3D# >=20 > + >=20 > +#langdef en-US "english" >=20 > + >=20 > +#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too many > arguments. Try help http.\r\n" >=20 > +#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few > arguments. Try help http.\r\n" >=20 > +#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid > argument - '%H%s%N'. Try help http.\r\n" >=20 > +#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown flag= - > '%H%s%N'. Try help http.\r\n" >=20 > +#string STR_GEN_FILE_OPEN_FAIL #language en-US "%H%s%N: Cannot open > file - '%H%s%N'\r\n" >=20 > +#string STR_GEN_CRLF #language en-US "\r\n" >=20 > + >=20 > +#string STR_HTTP_ERR_NO_NIC #language en-US "No network interface > card found.\r\n" >=20 > +#string STR_HTTP_ERR_NIC_NAME #language en-US "Failed to get the na= me > of the network interface card number %d - %r\r\n" >=20 > +#string STR_HTTP_ERR_OPEN_PROTOCOL #language en-US "Unable to open > HTTP protocol on '%H%s%N' - %r\r\n" >=20 > +#string STR_HTTP_ERR_CONFIGURE #language en-US "Unable to configure > HTTP protocol on '%H%s%N' - %r\r\n" >=20 > +#string STR_HTTP_ERR_DOWNLOAD #language en-US "Unable to download > the file '%H%s%N' on '%H%s%N' - %r\r\n" >=20 > +#string STR_HTTP_ERR_WRITE #language en-US "Unable to write into= file > '%H%s%N' - %r\r\n" >=20 > +#string STR_HTTP_ERR_NIC_NOT_FOUND #language en-US "Network Interface > Card '%H%s%N' not found.\r\n" >=20 > +#string STR_HTTP_ERR_STATUSCODE #language en-US "\r'%H%s%N' reports > '%s' for '%H%s%N' \r\n" >=20 > +#string STR_HTTP_DOWNLOADING #language en-US "Downloading > '%H%s%N'\r\n" >=20 > + >=20 > +#string STR_GET_HELP_HTTP #language en-US "" >=20 > +".TH http 0 "Download a file from HTTP server."\r\n" >=20 > +".SH NAME\r\n" >=20 > +"Download a file from HTTP server.\r\n" >=20 > +".SH SYNOPSIS\r\n" >=20 > +" \r\n" >=20 > +"HTTP [-i interface] [-l port] [-t timeout] [-s size] [-m] [-k]\r\n" >=20 > +" [localfilepath]\r\n" >=20 > +".SH OPTIONS\r\n" >=20 > +" \r\n" >=20 > +" -i interface - Specifies an adapter name, i.e., eth0.\r\n" >=20 > +" -k Keep the downloaded file even if there was an erro= r.\r\n" >=20 > +" If this parameter is not used, the file will be de= leted.\r\n" >=20 > +" -l port - Specifies the local port number. Default value is = 0\r\n" >=20 > +" and the port number is automatically assigned.\r\n= " >=20 > +" -m Measure and report download time (in seconds). \r\= n" >=20 > +" -s size The size of the download buffer for a chunk, in by= tes.\r\n" >=20 > +" Default is 32K. Note that larger buffer does not i= mply\r\n" >=20 > +" better speed.\r\n" >=20 > +" -t timeout - The number of seconds to wait for completion of\r\= n" >=20 > +" requests and responses. Default is 0 which is 'aut= omatic'.\r\n" >=20 > +" %HURL%N\r\n" >=20 > +" Two types of providing of URLs are supported:\r\n" >=20 > +" 1. tftp-like, where host and http_uri are separate parameters\r\n" >=20 > +" (example: host /host_uri), and\r\n\" >=20 > +" 2. wget-like, where host and host_uri is one parameter.\r\n" >=20 > +" (example: host/host_uri)\r\n" >=20 > +"\r\n" >=20 > +" host - Specifies HTTP Server address.\r\n >=20 > + Can be either IPv4 address or 'http (or https):/= /addr'\r\n >=20 > + Can use addresses resolvable by DNS as well. \r\= n >=20 > + Port can be specified after ':' if needed. \r\n >=20 > + By default port 80 is used.\r\n" >=20 > +" http_uri - HTTP server URI to download the file.\r\n" >=20 > +"\r\n" >=20 > +" localfilepath - Local destination file path.\r\n" >=20 > +".SH DESCRIPTION\r\n" >=20 > +" \r\n" >=20 > +"NOTES:\r\n" >=20 > +" 1. The HTTP command allows geting of the file specified by its 'http_= uri'\r\n" >=20 > +" path from the HTTP server specified by its 'host' IPv4 address. If= the\r\n" >=20 > +" optional 'localfilepath' parameter is provided, the downloaded fil= e is\r\n" >=20 > +" stored locally using the provided file path. If the local file pat= h is\r\n" >=20 > +" not specified, the file is stored in the current directory using t= he file\r\n" >=20 > +" server's name.\r\n" >=20 > +" 2. Before using the HTTP command, the network interface intended to > be\r\n" >=20 > +" used to retrieve the file must be configured. This configuration m= ay be\r\n" >=20 > +" done by means of the 'ifconfig' command.\r\n" >=20 > +" 3. If a network interface is defined with the '-i' option then only t= his\r\n" >=20 > +" interface will be used to retrieve the remote file. Otherwise, all > network\r\n" >=20 > +" interfaces are tried in the order they have been discovered during= the\r\n" >=20 > +" DXE phase.\r\n" >=20 > +".SH EXAMPLES\r\n" >=20 > +" \r\n" >=20 > +"EXAMPLES:\r\n" >=20 > +" * To get the file "dir1/file1.dat" from the HTTP server 192.168.1.1, = port 8080, > and\r\n" >=20 > +" store it as file2.dat in the current directory (use tftp-like URL f= ormat) :\r\n" >=20 > +" fs0:\> http 192.168.1.1:8080 dir1/file1.dat file2.dat\r\n" >=20 > +" * To get the file /image.bin via HTTPS from server 192.168.1.1 at por= t 443 > \r\n" >=20 > +" (default HTTPS port), and store it in the current directory: \r\n" >=20 > +" fs0:\> http https://192.168.1.1 image.bin\r\n" >=20 > +" To get an index file from http://google.com and place it into the \= r\n" >=20 > +" current directory:\r\n" >=20 > +" fs0:\> http google.com index.html\r\n" >=20 > +".SH RETURNVALUES\r\n" >=20 > +" \r\n" >=20 > +"RETURN VALUES:\r\n" >=20 > +" SHELL_SUCCESS The action was completed as requested.\r\n" >=20 > +" SHELL_INVALID_PARAMETER One of the passed-in parameters was > incorrectly\r\n" >=20 > +" formatted or its value was out of bounds.\r= \n" >=20 > +" HTTP_ERROR No EFI errors, but the server reported a st= atus > code\r\n" >=20 > +" which should be treated as an error. If an = error body sent\r\n" >=20 > +" by the server, and -k parameter is on comma= nd line, >=20 > +" the file wil be saved either as localfilepa= th filename,\r\n" >=20 > +" or as an URI name in the current directory.= \r\n" >=20 > +" If '/' is at the end of the URL, and no loc= afilepath filename\r\n" >=20 > +" is given on the command line, the file will= be retrieved as\r\n" >=20 > +" index.html.\r\n" >=20 > diff --git a/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c > b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c > new file mode 100644 > index 000000000000..7bd5b46d3997 > --- /dev/null > +++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c > @@ -0,0 +1,53 @@ > +/** @file >=20 > + Entrypoint of "http" shell standalone application. >=20 > + >=20 > + Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved. >=20 > + Copyright (c) 2015, ARM Ltd. All rights reserved.
>=20 > + Copyright (c) 2020, Broadcom. All rights reserved.
>=20 > + >=20 > + SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > + >=20 > +**/ >=20 > +#include "Http.h" >=20 > + >=20 > +/* >=20 > + * String token ID of help message text. >=20 > + * Shell supports to find help message in the resource section of an >=20 > + * application image if * .MAN file is not found. >=20 > + * This global variable is added to make build tool recognizes >=20 > + * that the help string is consumed by user and then build tool will >=20 > + * add the string into the resource section. >=20 > + * Thus the application can use '-?' option to show help message in Shel= l. >=20 > + */ >=20 > +GLOBAL_REMOVE_IF_UNREFERENCED >=20 > +EFI_STRING_ID mStringHelpTokenId =3D STRING_TOKEN (STR_GET_HELP_HTTP); >=20 > + >=20 > +/** >=20 > + Entry point of Http standalone application. >=20 > + >=20 > + @param ImageHandle The image handle of the process. >=20 > + @param SystemTable The EFI System Table pointer. >=20 > + >=20 > + @retval EFI_SUCCESS Http command is executed sucessfully. >=20 > + @retval EFI_ABORTED HII package was failed to initialize. >=20 > + @retval others Other errors when executing http command= . >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +HttpAppInitialize ( >=20 > + IN EFI_HANDLE ImageHandle, >=20 > + IN EFI_SYSTEM_TABLE *SystemTable >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + mHttpHiiHandle =3D InitializeHiiPackage (ImageHandle); >=20 > + if (mHttpHiiHandle =3D=3D NULL) { >=20 > + return EFI_ABORTED; >=20 > + } >=20 > + >=20 > + Status =3D (EFI_STATUS)RunHttp (ImageHandle, SystemTable); >=20 > + >=20 > + HiiRemovePackages (mHttpHiiHandle); >=20 > + >=20 > + return Status; >=20 > +} >=20 > 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 >=20 > +# Provides Shell 'http' standalone application. >=20 > +# >=20 > +# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved. >=20 > +# Copyright (c) 2015, ARM Ltd. All rights reserved.
>=20 > +# Copyright (c) 2020, Broadcom. All rights reserved.
>=20 > +# >=20 > +# SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > +# >=20 > +# >=20 > +## >=20 > + >=20 > +[Defines] >=20 > + INF_VERSION =3D 0x00010006 >=20 > + BASE_NAME =3D http >=20 > + FILE_GUID =3D 56B00FB7-91D2-869B-CE5C-26CD1A89C73= C >=20 > + MODULE_TYPE =3D UEFI_APPLICATION >=20 > + VERSION_STRING =3D 1.0 >=20 > + ENTRY_POINT =3D HttpAppInitialize >=20 > +# >=20 > +# This flag specifies whether HII resource section is generated into PE= image. >=20 > +# >=20 > + UEFI_HII_RESOURCE_SECTION =3D TRUE >=20 > + >=20 > +[Sources.common] >=20 > + Http.c >=20 > + HttpApp.c >=20 > + Http.h >=20 > + Http.uni >=20 > + >=20 > +[Packages] >=20 > + EmbeddedPkg/EmbeddedPkg.dec >=20 > + MdeModulePkg/MdeModulePkg.dec >=20 > + MdePkg/MdePkg.dec >=20 > + NetworkPkg/NetworkPkg.dec >=20 > + ShellPkg/ShellPkg.dec >=20 > + >=20 > +[LibraryClasses] >=20 > + BaseLib >=20 > + BaseMemoryLib >=20 > + DebugLib >=20 > + FileHandleLib >=20 > + HiiLib >=20 > + HttpLib >=20 > + MemoryAllocationLib >=20 > + NetLib >=20 > + ShellLib >=20 > + UefiApplicationEntryPoint >=20 > + UefiBootServicesTableLib >=20 > + UefiHiiServicesLib >=20 > + UefiLib >=20 > + UefiRuntimeServicesTableLib >=20 > + >=20 > +[Protocols] >=20 > + gEfiHiiPackageListProtocolGuid ## CONSUMES >=20 > + gEfiHttpProtocolGuid ## CONSUMES >=20 > + gEfiHttpServiceBindingProtocolGuid ## CONSUMES >=20 > + gEfiManagedNetworkServiceBindingProtocolGuid ## CONSUMES >=20 > diff --git > a/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.c > b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.c > new file mode 100644 > index 000000000000..ba654749a075 > --- /dev/null > +++ > b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.c > @@ -0,0 +1,134 @@ > +/** @file >=20 > + Produce "http" shell dynamic command. >=20 > + >=20 > + Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved. >=20 > + Copyright (c) 2015, ARM Ltd. All rights reserved.
>=20 > + Copyright (c) 2020, Broadcom. All rights reserved.
>=20 > + >=20 > + SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > + >=20 > +**/ >=20 > +#include >=20 > +#include "Http.h" >=20 > + >=20 > +/** >=20 > + This is the shell command handler function pointer callback type. Thi= s >=20 > + function handles the command when it is invoked in the shell. >=20 > + >=20 > + @param[in] This The instance of the >=20 > + EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. >=20 > + @param[in] SystemTable The pointer to the system table. >=20 > + @param[in] ShellParameters The parameters associated with the comma= nd. >=20 > + @param[in] Shell The instance of the shell protocol used = in >=20 > + the context of processing this command. >=20 > + >=20 > + @return EFI_SUCCESS the operation was sucessful >=20 > + @return other the operation failed. >=20 > +**/ >=20 > +SHELL_STATUS >=20 > +EFIAPI >=20 > +HttpCommandHandler ( >=20 > + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, >=20 > + IN EFI_SYSTEM_TABLE *SystemTable, >=20 > + IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, >=20 > + IN EFI_SHELL_PROTOCOL *Shell >=20 > + ) >=20 > +{ >=20 > + gEfiShellParametersProtocol =3D ShellParameters; >=20 > + gEfiShellProtocol =3D Shell; >=20 > + >=20 > + return RunHttp (gImageHandle, SystemTable); >=20 > +} >=20 > + >=20 > +/** >=20 > + This is the command help handler function pointer callback type. This >=20 > + function is responsible for displaying help information for the associ= ated >=20 > + command. >=20 > + >=20 > + @param[in] This The instance of the > EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. >=20 > + @param[in] Language The pointer to the language string to use. >=20 > + >=20 > + @return string Pool allocated help string, must be freed by ca= ller >=20 > +**/ >=20 > +CHAR16 * >=20 > +EFIAPI >=20 > +HttpCommandGetHelp ( >=20 > + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, >=20 > + IN CONST CHAR8 *Language >=20 > + ) >=20 > +{ >=20 > + return HiiGetString(mHttpHiiHandle, >=20 > + STRING_TOKEN (STR_GET_HELP_HTTP), >=20 > + Language); >=20 > +} >=20 > + >=20 > +EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mHttpDynamicCommand =3D { >=20 > + HTTP_APP_NAME, >=20 > + HttpCommandHandler, >=20 > + HttpCommandGetHelp >=20 > +}; >=20 > + >=20 > +/** >=20 > + Entry point of Http Dynamic Command. >=20 > + >=20 > + Produce the DynamicCommand protocol to handle "http" command. >=20 > + >=20 > + @param ImageHandle The image handle of the process. >=20 > + @param SystemTable The EFI System Table pointer. >=20 > + >=20 > + @retval EFI_SUCCESS Http command is executed sucessfully. >=20 > + @retval EFI_ABORTED HII package was failed to initialize. >=20 > + @retval others Other errors when executing http command= . >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +HttpCommandInitialize ( >=20 > + IN EFI_HANDLE ImageHandle, >=20 > + IN EFI_SYSTEM_TABLE *SystemTable >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + >=20 > + mHttpHiiHandle =3D InitializeHiiPackage (ImageHandle); >=20 > + if (mHttpHiiHandle =3D=3D NULL) { >=20 > + return EFI_ABORTED; >=20 > + } >=20 > + >=20 > + Status =3D gBS->InstallProtocolInterface ( >=20 > + &ImageHandle, >=20 > + &gEfiShellDynamicCommandProtocolGuid, >=20 > + EFI_NATIVE_INTERFACE, >=20 > + &mHttpDynamicCommand >=20 > + ); >=20 > + ASSERT_EFI_ERROR (Status); >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + Http driver unload handler. >=20 > + >=20 > + @param ImageHandle The image handle of the process. >=20 > + >=20 > + @retval EFI_SUCCESS The image is unloaded. >=20 > + @retval Others Failed to unload the image. >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +HttpUnload ( >=20 > + IN EFI_HANDLE ImageHandle >=20 > +) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + Status =3D gBS->UninstallProtocolInterface ( >=20 > + ImageHandle, >=20 > + &gEfiShellDynamicCommandProtocolGuid, >=20 > + &mHttpDynamicCommand >=20 > + ); >=20 > + if (EFI_ERROR (Status)) { >=20 > + return Status; >=20 > + } >=20 > + >=20 > + HiiRemovePackages (mHttpHiiHandle); >=20 > + >=20 > + return EFI_SUCCESS; >=20 > +} >=20 > 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 >=20 > +# Provides Shell 'http' dynamic command. >=20 > +# >=20 > +# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved. >=20 > +# Copyright (c) 2015, ARM Ltd. All rights reserved.
>=20 > +# Copyright (c) 2020, Broadcom. All rights reserved.
>=20 > +# >=20 > +# SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > +# >=20 > +# >=20 > +## >=20 > + >=20 > +[Defines] >=20 > + INF_VERSION =3D 0x00010006 >=20 > + BASE_NAME =3D httpDynamicCommand >=20 > + FILE_GUID =3D 19618BCE-55AE-09C6-37E9-4CE04084C7A= 1 >=20 > + MODULE_TYPE =3D DXE_DRIVER >=20 > + VERSION_STRING =3D 1.0 >=20 > + ENTRY_POINT =3D HttpCommandInitialize >=20 > + UNLOAD_IMAGE =3D HttpUnload >=20 > +# >=20 > +# This flag specifies whether HII resource section is generated into PE= image. >=20 > +# >=20 > + UEFI_HII_RESOURCE_SECTION =3D TRUE >=20 > + >=20 > +[Sources.common] >=20 > + Http.c >=20 > + HttpDynamicCommand.c >=20 > + Http.h >=20 > + Http.uni >=20 > + >=20 > +[Packages] >=20 > + EmbeddedPkg/EmbeddedPkg.dec >=20 > + MdePkg/MdePkg.dec >=20 > + MdeModulePkg/MdeModulePkg.dec >=20 > + NetworkPkg/NetworkPkg.dec >=20 > + ShellPkg/ShellPkg.dec >=20 > + >=20 > +[LibraryClasses] >=20 > + BaseLib >=20 > + BaseMemoryLib >=20 > + DebugLib >=20 > + FileHandleLib >=20 > + HiiLib >=20 > + HttpLib >=20 > + MemoryAllocationLib >=20 > + NetLib >=20 > + ShellLib >=20 > + UefiBootServicesTableLib >=20 > + UefiDriverEntryPoint >=20 > + UefiHiiServicesLib >=20 > + UefiLib >=20 > + UefiRuntimeServicesTableLib >=20 > + >=20 > +[Protocols] >=20 > + gEfiHiiPackageListProtocolGuid ## CONSUMES >=20 > + gEfiHttpProtocolGuid ## CONSUMES >=20 > + gEfiHttpServiceBindingProtocolGuid ## CONSUMES >=20 > + gEfiManagedNetworkServiceBindingProtocolGuid ## CONSUMES >=20 > + gEfiShellDynamicCommandProtocolGuid ## PRODUCES >=20 > + >=20 > +[DEPEX] >=20 > + TRUE >=20 > 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, 0x= 0e, 0xd4 } > \ >=20 > } >=20 >=20 >=20 > +#define SHELL_HTTP_HII_GUID \ >=20 > + { \ >=20 > + 0x390f84b3, 0x221c, 0x4d9e, { 0xb5, 0x06, 0x6d, 0xb9, 0x42, 0x3e, 0x= 0a, > 0x7e } \ >=20 > + } >=20 >=20 >=20 > #define SHELL_BCFG_HII_GUID \ >=20 > { \ >=20 > @@ -75,6 +79,7 @@ extern EFI_GUID gShellLevel3HiiGuid; > extern EFI_GUID gShellNetwork1HiiGuid; >=20 > extern EFI_GUID gShellNetwork2HiiGuid; >=20 > extern EFI_GUID gShellTftpHiiGuid; >=20 > +extern EFI_GUID gShellHttpHiiGuid; >=20 > extern EFI_GUID gShellBcfgHiiGuid; >=20 >=20 >=20 > #endif >=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, {0xb0= , 0xb7, 0xfa, > 0x99, 0x9c, 0x62, 0x37, 0xae}} >=20 > gShellNetwork2HiiGuid =3D {0x174b2b5, 0xf505, 0x4b12, {0xaa,= 0x60, 0x59, > 0xdf, 0xf8, 0xd6, 0xea, 0x37}} >=20 > gShellTftpHiiGuid =3D {0x738a9314, 0x82c1, 0x4592, {0x8f= , 0xf7, 0xc1, > 0xbd, 0xf1, 0xb2, 0x0e, 0xd4}} >=20 > + gShellHttpHiiGuid =3D {0x390f84b3, 0x221c, 0x4d9e, {0xb5= , 0x06, 0x6d, > 0xb9, 0x42, 0x3e, 0x0a, 0x7e}} >=20 > gShellBcfgHiiGuid =3D {0x5f5f605d, 0x1583, 0x4a2d, {0xa6= , 0xb2, 0xeb, > 0x12, 0xda, 0xb4, 0xa2, 0xb6}} >=20 > gShellAcpiViewHiiGuid =3D {0xda8ccdf4, 0xed8f, 0x4ffc, {0xb5= , 0xef, 0x2e, > 0xf5, 0x5e, 0x24, 0x93, 0x2a}} >=20 > # FILE_GUID as defined in ShellPkg/Application/Shell/Shell.inf >=20 > 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 >=20 > } >=20 > ShellPkg/DynamicCommand/TftpDynamicCommand/TftpApp.inf >=20 > + > ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf { >=20 > + >=20 > + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE >=20 > + } >=20 > + ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf >=20 > ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf { >=20 > >=20 > gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE >=20 > -- > 2.26.2.266.ge870325ee8