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.web10.48304.1597684519377935225 for ; Mon, 17 Aug 2020 10:15:19 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=none, err=permanent DNS error (domain: linux.intel.com, ip: 192.55.52.88, mailfrom: maciej.rabeda@linux.intel.com) IronPort-SDR: tVCT0eg+4Gc/DOpQ9B/yW1k62djtbpV/9GjSRsHrD54o+80SzQs4Rtl3dZnLQv2OM0KAkWGRl/ TWWD/YW+RGsA== X-IronPort-AV: E=McAfee;i="6000,8403,9716"; a="172807428" X-IronPort-AV: E=Sophos;i="5.76,324,1592895600"; d="scan'208";a="172807428" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Aug 2020 10:15:17 -0700 IronPort-SDR: XMjFjToUrPiBsCRt2wYZBSmmiwqezDMQeV4MFpZzC6nsdINkvOoya6c7HVry3dwav7n7Y2D6bB 2bVY2Ka/Fjxg== X-IronPort-AV: E=Sophos;i="5.76,324,1592895600"; d="scan'208";a="471495691" Received: from mrabeda-mobl.ger.corp.intel.com (HELO [10.213.18.113]) ([10.213.18.113]) by orsmga005-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Aug 2020 10:15:11 -0700 Subject: Re: [PATCH v5 1/1] ShellPkg/DynamicCommand: add HttpDynamicCommand To: Vladimir Olovyannikov , "Gao, Zhichao" , devel@edk2.groups.io Cc: Laszlo Ersek , Samer El-Haj-Mahmoud , "Wu, Jiaxin" , "Fu, Siyuan" , "Ni, Ray" , "Gao, Liming" , Nd References: <20200727164830.25829-1-vladimir.olovyannikov@broadcom.com> <20200727164830.25829-2-vladimir.olovyannikov@broadcom.com> <25b5ce9498095e68650b8817e4523714@mail.gmail.com> From: "Maciej Rabeda" Message-ID: Date: Mon, 17 Aug 2020 19:15:02 +0200 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Thunderbird/68.11.0 MIME-Version: 1.0 In-Reply-To: <25b5ce9498095e68650b8817e4523714@mail.gmail.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Content-Language: pl Hi Vladimir, I cannot apply the patch via 'git am'. Is your git configured in a manner described here? https://github.com/tianocore/tianocore.github.io/wiki/Laszlo's-unkempt-git-guide-for-edk2-contributors-and-maintainers Laszlo, Were you able to apply this patch from .eml file? Thanks, Maciej On 17-Aug-20 17:46, Vladimir Olovyannikov wrote: > Hi Gao, > > Thanks for reviewing. > As you suggest, I will postpone the next patchset submission until > NetworkPkg maintainer(s) review. > >> -----Original Message----- >> From: Gao, Zhichao >> Sent: Sunday, August 16, 2020 6:48 PM >> To: Vladimir Olovyannikov ; >> devel@edk2.groups.io >> Cc: Laszlo Ersek ; Samer El-Haj-Mahmoud > Haj-Mahmoud@arm.com>; Maciej Rabeda >> ; Wu, Jiaxin ; Fu, >> Siyuan ; Ni, Ray ; Gao, Liming >> ; Nd >> Subject: RE: [PATCH v5 1/1] ShellPkg/DynamicCommand: add >> HttpDynamicCommand >> >> 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 >>> Introduce an http client utilizing EDK2 HTTP protocol, to >>> allow fast image downloading from http/https servers. >>> HTTP download speed is usually faster than tftp. >>> The client is based on the same approach as tftp dynamic command, and >>> uses the same UEFI Shell command line parameters. This makes it easy >>> integrating http into existing UEFI Shell scripts. >>> Note that to enable HTTP download, feature Pcd >>> gEfiNetworkPkgTokenSpaceGuid.PcdAllowHttpConnections must >>> be set to TRUE. >>> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2860 >>> >>> Signed-off-by: Vladimir Olovyannikov >> >>> CC: Samer El-Haj-Mahmoud >>> CC: Laszlo Ersek >>> Cc: Zhichao Gao >>> Cc: Maciej Rabeda >>> Cc: Jiaxin Wu >>> Cc: Siyuan Fu >>> Cc: Ray Ni >>> Cc: Liming Gao >>> Cc: Nd >>> --- >>> 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 >>> 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 >>> >>> + 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 >>> >>> +EFI_HII_HANDLE mHttpHiiHandle; >>> >>> + >>> >>> +/* >>> >>> + 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 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"[ > ]" >>> + >>> >>> +// String descriptions for server errors >>> >>> +STATIC CONST CHAR16 *ErrStatusDesc[] = >>> >>> +{ >>> >>> + L"400 Bad Request", >>> >>> + L"401 Unauthorized", >>> >>> + L"402 Payment required", >>> >>> + L"403 Forbidden", >>> >>> + L"404 Not Found", >>> >>> + L"405 Method not allowed", >>> >>> + L"406 Not acceptable", >>> >>> + L"407 Proxy authentication required", >>> >>> + L"408 Request time out", >>> >>> + L"409 Conflict", >>> >>> + L"410 Gone", >>> >>> + L"411 Length required", >>> >>> + L"412 Precondition failed", >>> >>> + L"413 Request entity too large", >>> >>> + L"414 Request URI to large", >>> >>> + L"415 Unsupported media type", >>> >>> + L"416 Requested range not satisfied", >>> >>> + L"417 Expectation failed", >>> >>> + L"500 Internal server error", >>> >>> + L"501 Not implemented", >>> >>> + L"502 Bad gateway", >>> >>> + L"503 Service unavailable", >>> >>> + L"504 Gateway timeout", >>> >>> + L"505 HTTP version not supported" >>> >>> +}; >>> >>> + >>> >>> +// Local File Handle >>> >>> +STATIC SHELL_FILE_HANDLE mFileHandle = NULL; >>> >>> + >>> >>> +// Path of the local file, Unicode encoded >>> >>> +STATIC CONST CHAR16 *mLocalFilePath; >>> >>> + >>> >>> +STATIC BOOLEAN gRequestCallbackComplete = FALSE; >>> >>> +STATIC BOOLEAN gResponseCallbackComplete = FALSE; >>> >>> + >>> >>> +STATIC BOOLEAN gHttpError; >>> >>> + >>> >>> +/** >>> >>> + 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 >>> >>> + ) >>> >>> +{ >>> >>> + ASSERT(String != NULL); >>> >>> + ASSERT(*String!= NULL); >>> >>> + // >>> >>> + // Remove any spaces and tabs at the beginning of the (*String). >>> >>> + // >>> >>> + while (((*String)[0] == L' ') || ((*String)[0] == L'\t')) { >>> >>> + CopyMem ( >>> >>> + (*String), >>> >>> + (*String) + 1, >>> >>> + StrSize ((*String)) - sizeof((*String)[0]) >>> >>> + ); >>> >>> + } >>> >>> + >>> >>> + // >>> >>> + // Remove any spaces and tabs at the end of the (*String). >>> >>> + // >>> >>> + while ((StrLen (*String) > 0) && >>> >>> + (((*String)[StrLen ((*String)) - 1] == L' ') || >>> >>> + ((*String)[StrLen ((*String)) - 1] == L'\t')) >>> >>> + ) { >>> >>> + (*String)[StrLen ((*String)) - 1] = CHAR_NULL; >>> >>> + } >>> >>> + >>> >>> + 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 = TRUE; >>> >>> +} >>> >>> + >>> >>> +STATIC >>> >>> +VOID >>> >>> +EFIAPI >>> >>> +ResponseCallback ( >>> >>> + IN EFI_EVENT Event, >>> >>> + IN VOID *Context >>> >>> +) >>> >>> +{ >>> >>> + gResponseCallbackComplete = TRUE; >>> >>> +} >>> >>> + >>> >>> + >>> >>> +/** >>> >>> + 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 > protocol >> GUID >>> + and get from the child the interface of the protocol identified by > its >> GUID. >>> + >>> >>> + @param[in] ControllerHandle Controller handle. >>> >>> + @param[in] ServiceBindingProtocolGuid Service binding protocol > GUID >> of the >>> + service to be created. >>> >>> + @param[in] ProtocolGuid GUID of the protocol to be > open. >>> + @param[out] ChildHandle Address where the handler > of the >>> + created child is returned. > NULL is >>> + returned in case of error. >>> >>> + @param[out] Interface Address where a pointer to > the >>> + protocol interface is > returned in >>> + case of success. >>> >>> + >>> >>> + @return EFI_SUCCESS The child was created and the protocol > opened. >>> + @return Others Either the creation of the child or the > opening >>> + of the protocol failed. >>> >>> +**/ >>> >>> +STATIC >>> >>> +EFI_STATUS >>> >>> +CreateServiceChildAndOpenProtocol ( >>> >>> + IN EFI_HANDLE ControllerHandle, >>> >>> + IN EFI_GUID *ServiceBindingProtocolGuid, >>> >>> + IN EFI_GUID *ProtocolGuid, >>> >>> + OUT EFI_HANDLE *ChildHandle, >>> >>> + OUT VOID **Interface >>> >>> + ); >>> >>> + >>> >>> +/** >>> >>> + Close the protocol identified by its GUID on the child handle of > the >> service >>> + identified by its service binding protocol GUID, then destroy the > child >>> + handle. >>> >>> + >>> >>> + @param[in] ControllerHandle Controller handle. >>> >>> + @param[in] ServiceBindingProtocolGuid Service binding protocol > GUID >> of the >>> + service to be destroyed. >>> >>> + @param[in] ProtocolGuid GUID of the protocol to be > closed. >>> + @param[in] ChildHandle Handle of the child to be > destroyed. >>> + >>> >>> +**/ >>> >>> +STATIC >>> >>> +VOID >>> >>> +CloseProtocolAndDestroyServiceChild ( >>> >>> + IN EFI_HANDLE ControllerHandle, >>> >>> + IN EFI_GUID *ServiceBindingProtocolGuid, >>> >>> + IN EFI_GUID *ProtocolGuid, >>> >>> + IN EFI_HANDLE ChildHandle >>> >>> + ); >>> >>> + >>> >>> + >>> >>> +/** >>> >>> + Worker function that download the data of a file from an HTTP > server >> given >>> + the path of the file and its size. >>> >>> + >>> >>> + @param[in] Context A pointer to the download context. >>> >>> + >>> >>> + @retval EFI_SUCCESS The file was downloaded. >>> >>> + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. >>> >>> + @retval Others The downloading of the file >>> >>> + from the server failed. >>> >>> + >>> >>> +**/ >>> >>> +STATIC >>> >>> +EFI_STATUS >>> >>> +DownloadFile ( >>> >>> + IN DOWNLOAD_CONTEXT *Context >>> >>> + ); >>> >>> + >>> >>> +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { >>> >>> + {L"-i", TypeValue}, >>> >>> + {L"-k", TypeFlag}, >>> >>> + {L"-l", TypeValue}, >>> >>> + {L"-s", TypeValue}, >>> >>> + {L"-t", TypeValue}, >>> >>> + {NULL , TypeMax} >>> >>> + }; >>> >>> + >>> >>> +/** >>> >>> + Function for 'http' command. >>> >>> + >>> >>> + @param[in] ImageHandle Handle to the Image (NULL if Internal). >>> >>> + @param[in] SystemTable Pointer to the System Table (NULL if > Internal). >>> + >>> >>> + @return SHELL_SUCCESS The 'http' command completed >> successfully. >>> + @return SHELL_ABORTED The Shell Library initialization > failed. >>> + @return SHELL_INVALID_PARAMETER At least one of the command's >>> arguments is >>> >>> + not valid. >>> >>> + @return SHELL_OUT_OF_RESOURCES A memory allocation failed. >>> >>> + @return SHELL_NOT_FOUND Network Interface Card not found. >>> >>> + @return SHELL_UNSUPPORTED Command was valid, but the server >>> returned >>> >>> + a status code indicating some > error. >>> + Examine the file requested for > error body. >>> + >>> >>> +**/ >>> >>> +SHELL_STATUS >>> >>> +RunHttp ( >>> >>> + IN EFI_HANDLE ImageHandle, >>> >>> + IN EFI_SYSTEM_TABLE *SystemTable >>> >>> + ) >>> >>> +{ >>> >>> + EFI_STATUS Status; >>> >>> + LIST_ENTRY *CheckPackage; >>> >>> + UINTN ParamCount; >>> >>> + UINTN HandleCount; >>> >>> + UINTN NicNumber; >>> >>> + UINTN InitialSize; >>> >>> + UINTN ParamOffset; >>> >>> + UINTN StartSize; >>> >>> + CHAR16 *ProblemParam; >>> >>> + CHAR16 >> NicName[IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH]; >>> + CHAR16 *Walker1; >>> >>> + CHAR16 *VStr; >>> >>> + CONST CHAR16 *UserNicName; >>> >>> + CONST CHAR16 *ValueStr; >>> >>> + CONST CHAR16 *RemoteFilePath; >>> >>> + CONST CHAR16 *Walker; >>> >>> + EFI_HTTP_CONFIG_DATA HttpConfigData; >>> >>> + EFI_HTTPv4_ACCESS_POINT IPv4Node; >>> >>> + EFI_HANDLE *Handles; >>> >>> + EFI_HANDLE ControllerHandle; >>> >>> + EFI_HANDLE HttpChildHandle; >>> >>> + DOWNLOAD_CONTEXT Context; >>> >>> + BOOLEAN NicFound; >>> >>> + >>> >>> + ProblemParam = NULL; >>> >>> + RemoteFilePath = NULL; >>> >>> + NicFound = FALSE; >>> >>> + Handles = NULL; >>> >>> + >>> >>> + // >>> >>> + // Initialize the Shell library (we must be in non-auto-init...) >>> >>> + // >>> >>> + ParamOffset = 0; >>> >>> + gHttpError = FALSE; >>> >>> + >>> >>> + Status = ShellInitialize (); >>> >>> + if (EFI_ERROR (Status)) { >>> >>> + ASSERT_EFI_ERROR (Status); >>> >>> + return SHELL_ABORTED; >>> >>> + } >>> >>> + >>> >>> + ZeroMem (&Context, sizeof (Context)); >>> >>> + >>> >>> + // >>> >>> + // Parse the command line. >>> >>> + // >>> >>> + Status = ShellCommandLineParse ( >>> >>> + ParamList, >>> >>> + &CheckPackage, >>> >>> + &ProblemParam, >>> >>> + TRUE); >> I prefer to put ');' in next line like other functions. >> >>> + if (EFI_ERROR (Status)) { >>> >>> + if ((Status == EFI_VOLUME_CORRUPTED) && >>> >>> + (ProblemParam != NULL) ) { >>> >>> + ShellPrintHiiEx ( >>> >>> + -1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), mHttpHiiHandle, >>> >>> + HTTP_APP_NAME, ProblemParam >>> >>> + ); >>> >>> + SHELL_FREE_NON_NULL (ProblemParam); >>> >>> + } else { >>> >>> + ASSERT (FALSE); >>> >>> + } >>> >>> + >>> >>> + goto Error; >>> >>> + } >>> >>> + >>> >>> + // >>> >>> + // Check the number of parameters >>> >>> + // >>> >>> + Status = EFI_INVALID_PARAMETER; >>> >>> + >>> >>> + ParamCount = ShellCommandLineGetCount (CheckPackage); >>> >>> + if (ParamCount > MAX_PARAM_COUNT) { >>> >>> + ShellPrintHiiEx ( >>> >>> + -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), >>> >>> + mHttpHiiHandle, HTTP_APP_NAME >>> >>> + ); >>> >>> + goto Error; >>> >>> + } >>> >>> + >>> >>> + if (ParamCount < MIN_PARAM_COUNT) { >>> >>> + ShellPrintHiiEx ( >>> >>> + -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), >>> >>> + mHttpHiiHandle, HTTP_APP_NAME >>> >>> + ); >>> >>> + goto Error; >>> >>> + } >>> >>> + >>> >>> + ZeroMem (&HttpConfigData, sizeof (HttpConfigData)); >>> >>> + ZeroMem (&IPv4Node, sizeof (IPv4Node)); >>> >>> + IPv4Node.UseDefaultAddress = TRUE; >>> >>> + >>> >>> + HttpConfigData.HttpVersion = HttpVersion11; >>> >>> + HttpConfigData.AccessPoint.IPv4Node = &IPv4Node; >>> >>> + >>> >>> + // >>> >>> + // Get the host address (not necessarily IPv4 format) >>> >>> + // >>> >>> + ValueStr = ShellCommandLineGetRawValue (CheckPackage, 1); >>> >>> + if (!ValueStr) { >>> >>> + ShellPrintHiiEx ( >>> >>> + -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), >> mHttpHiiHandle, >>> + HTTP_APP_NAME, ValueStr >>> >>> + ); >>> >>> + goto Error; >>> >>> + } else { >>> >>> + StartSize = 0; >>> >>> + if (!StrStr (ValueStr, L"://")) { >>> >>> + Context.ServerAddrAndProto = StrnCatGrow ( >>> >>> + &Context.ServerAddrAndProto, >>> >>> + &StartSize, >>> >>> + DEFAULT_HTTP_PROTO, >>> >>> + StrLen (DEFAULT_HTTP_PROTO) >>> >>> + ); >>> >>> + Context.ServerAddrAndProto = StrnCatGrow ( >>> >>> + &Context.ServerAddrAndProto, >>> >>> + &StartSize, >>> >>> + L"://", >>> >>> + StrLen (L"://") >>> >>> + ); >>> >>> + VStr = (CHAR16 *)ValueStr; >>> >>> + } else { >>> >>> + VStr = StrStr (ValueStr, L"://") + StrLen (L"://"); >>> >>> + } >>> >>> + >>> >>> + for (Walker1 = VStr; *Walker1; Walker1++) { >>> >>> + if (*Walker1 == L'/') { >>> >>> + break; >>> >>> + } >>> >>> + } >>> >>> + >>> >>> + if (*Walker1 == L'/') { >>> >>> + ParamOffset = 1; >>> >>> + RemoteFilePath = Walker1; >>> >>> + } >>> >>> + >>> >>> + Context.ServerAddrAndProto = StrnCatGrow ( >>> >>> + &Context.ServerAddrAndProto, >>> >>> + &StartSize, >>> >>> + ValueStr, >>> >>> + StrLen (ValueStr) - StrLen > (Walker1) >>> + ); >>> >>> + if (!Context.ServerAddrAndProto) { >>> >>> + Status = EFI_OUT_OF_RESOURCES; >>> >>> + goto Error; >>> >>> + } >>> >>> + } >>> >>> + >>> >>> + if (!RemoteFilePath) { >>> >>> + RemoteFilePath = ShellCommandLineGetRawValue (CheckPackage, 2); >>> >>> + if (!RemoteFilePath) { >>> >>> + // If no path given, assume just "/" >>> >>> + RemoteFilePath = L"/"; >>> >>> + } >>> >>> + } >>> >>> + >>> >>> + TrimSpaces ((CHAR16 **)&RemoteFilePath); >>> >>> + >>> >>> + if (ParamCount == MAX_PARAM_COUNT - ParamOffset) { >>> >>> + mLocalFilePath = ShellCommandLineGetRawValue ( >>> >>> + CheckPackage, >>> >>> + MAX_PARAM_COUNT - 1 - ParamOffset); >>> >>> + } else { >>> >>> + Walker = RemoteFilePath + StrLen (RemoteFilePath); >>> >>> + while ((--Walker) >= RemoteFilePath) { >>> >>> + if ((*Walker == L'\\') || >>> >>> + (*Walker == L'/' ) ) { >> It is better to remove the useless space in the above line at the end of > 'if' >> condition. >> >>> + break; >>> >>> + } >>> >>> + } >>> >>> + >>> >>> + mLocalFilePath = Walker + 1; >>> >>> + } >>> >>> + >>> >>> + if (!StrLen (mLocalFilePath)) { >>> >>> + mLocalFilePath = DEFAULT_HTML_FILE; >>> >>> + } >>> >>> + >>> >>> + InitialSize = 0; >>> >>> + Context.URI = StrnCatGrow ( >>> >>> + &Context.URI, >>> >>> + &InitialSize, >>> >>> + RemoteFilePath, >>> >>> + StrLen (RemoteFilePath) >>> >>> + ); >>> >>> + if (!Context.URI) { >>> >>> + Status = EFI_OUT_OF_RESOURCES; >>> >>> + goto Error; >>> >>> + } >>> >>> + >>> >>> + // >>> >>> + // Get the name of the Network Interface Card to be used if any. >>> >>> + // >>> >>> + UserNicName = ShellCommandLineGetValue (CheckPackage, L"-i"); >>> >>> + >>> >>> + ValueStr = ShellCommandLineGetValue (CheckPackage, L"-l"); >>> >>> + if (ValueStr != NULL) { >>> >>> + if (!StringToUint16 ( >>> >>> + ValueStr, >>> >>> + &HttpConfigData.AccessPoint.IPv4Node->LocalPort >>> >>> + ) >>> >>> + ) { >> I suggest to align the end ')' of StringToUint16 to align with the > parameters. >> And the end ')' of 'if' to go right next to the end ')' of > StringToUint16. > OK, will do. >>> + goto Error; >>> >>> + } >>> >>> + } >>> >>> + >>> >>> + Context.BufferSize = DEFAULT_BUF_SIZE; >>> >>> + >>> >>> + ValueStr = ShellCommandLineGetValue (CheckPackage, L"-s"); >>> >>> + if (ValueStr != NULL) { >>> >>> + Context.BufferSize = ShellStrToUintn (ValueStr); >>> >>> + if (!Context.BufferSize || Context.BufferSize > MAX_BUF_SIZE) { >>> >>> + ShellPrintHiiEx ( >>> >>> + -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), >>> >>> + mHttpHiiHandle, HTTP_APP_NAME, ValueStr >>> >>> + ); >>> >>> + goto Error; >>> >>> + } >>> >>> + } >>> >>> + >>> >>> + ValueStr = ShellCommandLineGetValue (CheckPackage, L"-t"); >>> >>> + if (ValueStr != NULL) { >>> >>> + HttpConfigData.TimeOutMillisec = (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' review. >> >> I am OK with other part of the patch. But I still need NetworkPkg > maintainers' >> help to review above issue and the implementation. >> There is no need to resend another patch if NetworkPkg maintainers are > OK >> with above issue and the implementation. > OK, I will postpone submission of the patch until NetworkPkg > maintainter(s) review. >> Thanks, >> Zhichao >> > Thank you, > Vladimir >>> + } >>> >>> + >>> >>> + // >>> >>> + // Locate all HTTP Service Binding protocols >>> >>> + // >>> >>> + Status = gBS->LocateHandleBuffer ( >>> >>> + ByProtocol, >>> >>> + &gEfiManagedNetworkServiceBindingProtocolGuid, >>> >>> + NULL, >>> >>> + &HandleCount, >>> >>> + &Handles >>> >>> + ); >>> >>> + if (EFI_ERROR (Status) || (HandleCount == 0)) { >>> >>> + ShellPrintHiiEx ( >>> >>> + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_NO_NIC), >> mHttpHiiHandle >>> + ); >>> >>> + if (!EFI_ERROR (Status)) { >>> >>> + Status = EFI_NOT_FOUND; >>> >>> + } >>> >>> + >>> >>> + goto Error; >>> >>> + } >>> >>> + >>> >>> + Status = EFI_NOT_FOUND; >>> >>> + >>> >>> + for (NicNumber = 0; >>> >>> + (NicNumber < HandleCount) && (Status != EFI_SUCCESS); >>> >>> + NicNumber++) { >>> >>> + ControllerHandle = Handles[NicNumber]; >>> >>> + >>> >>> + Status = GetNicName (ControllerHandle, NicNumber, NicName); >>> >>> + if (EFI_ERROR (Status)) { >>> >>> + ShellPrintHiiEx ( >>> >>> + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_NIC_NAME), >>> >>> + mHttpHiiHandle, NicNumber, Status >>> >>> + ); >>> >>> + continue; >>> >>> + } >>> >>> + >>> >>> + if (UserNicName != NULL) { >>> >>> + if (StrCmp (NicName, UserNicName) != 0) { >>> >>> + Status = EFI_NOT_FOUND; >>> >>> + continue; >>> >>> + } >>> >>> + NicFound = TRUE; >>> >>> + } >>> >>> + >>> >>> + Status = CreateServiceChildAndOpenProtocol ( >>> >>> + ControllerHandle, >>> >>> + &gEfiHttpServiceBindingProtocolGuid, >>> >>> + &gEfiHttpProtocolGuid, >>> >>> + &HttpChildHandle, >>> >>> + (VOID**)&Context.Http >>> >>> + ); >>> >>> + if (EFI_ERROR (Status)) { >>> >>> + ShellPrintHiiEx ( >>> >>> + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_OPEN_PROTOCOL), >>> >>> + mHttpHiiHandle, NicName, Status >>> >>> + ); >>> >>> + continue; >>> >>> + } >>> >>> + >>> >>> + Status = Context.Http->Configure (Context.Http, &HttpConfigData); >>> >>> + if (EFI_ERROR (Status)) { >>> >>> + ShellPrintHiiEx ( >>> >>> + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_CONFIGURE), >>> >>> + mHttpHiiHandle, NicName, Status >>> >>> + ); >>> >>> + continue; >>> >>> + } >>> >>> + >>> >>> + Context.Flags = 0; >>> >>> + if (ShellCommandLineGetFlag (CheckPackage, L"-m")) { >>> >>> + Context.Flags |= DL_FLAG_TIME; >>> >>> + } >>> >>> + >>> >>> + if (ShellCommandLineGetFlag (CheckPackage, L"-k")) { >>> >>> + Context.Flags |= DL_FLAG_KEEP_BAD; >>> >>> + } >>> >>> + >>> >>> + Status = DownloadFile (&Context); >>> >>> + >>> >>> + ShellPrintHiiEx ( >>> >>> + -1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF), mHttpHiiHandle >>> >>> + ); >>> >>> + >>> >>> + CloseProtocolAndDestroyServiceChild ( >>> >>> + ControllerHandle, >>> >>> + &gEfiHttpServiceBindingProtocolGuid, >>> >>> + &gEfiHttpProtocolGuid, >>> >>> + HttpChildHandle >>> >>> + ); >>> >>> + >>> >>> + if (EFI_ERROR (Status)) { >>> >>> + ShellPrintHiiEx ( >>> >>> + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_DOWNLOAD), >>> >>> + mHttpHiiHandle, RemoteFilePath, NicName, Status >>> >>> + ); >>> >>> + // If a user aborted the operation, do not try another > controller. >>> + if (Status == EFI_ABORTED) { >>> >>> + goto Error; >>> >>> + } >>> >>> + } >>> >>> + >>> >>> + if (gHttpError) { >>> >>> + // >>> >>> + // This is not related to connection, so no need to repeat with >>> >>> + // another interface. >>> >>> + // >>> >>> + break; >>> >>> + } >>> >>> + } >>> >>> + >>> >>> + if ((UserNicName != NULL) && (!NicFound)) { >>> >>> + ShellPrintHiiEx ( >>> >>> + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_NIC_NOT_FOUND), >>> >>> + mHttpHiiHandle, 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 = ShellStrToUintn (ValueStr); >>> >>> + if (Val > MAX_UINT16) { >>> >>> + ShellPrintHiiEx ( >>> >>> + -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), >>> >>> + mHttpHiiHandle, HTTP_APP_NAME, ValueStr >>> >>> + ); >>> >>> + return FALSE; >>> >>> + } >>> >>> + >>> >>> + *Value = (UINT16)Val; >>> >>> + return TRUE; >>> >>> +} >>> >>> + >>> >>> +/** >>> >>> + Get the name of the NIC. >>> >>> + >>> >>> + @param[in] ControllerHandle The network physical device handle. >>> >>> + @param[in] NicNumber The network physical device number. >>> >>> + @param[out] NicName Address where to store the NIC name. >>> >>> + The memory area has to be at least >>> >>> + > IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH >>> + double byte wide. >>> >>> + >>> >>> + @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 = CreateServiceChildAndOpenProtocol ( >>> >>> + ControllerHandle, >>> >>> + &gEfiManagedNetworkServiceBindingProtocolGuid, >>> >>> + &gEfiManagedNetworkProtocolGuid, >>> >>> + &MnpHandle, >>> >>> + (VOID**)&Mnp >>> >>> + ); >>> >>> + if (EFI_ERROR (Status)) { >>> >>> + goto Error; >>> >>> + } >>> >>> + >>> >>> + Status = Mnp->GetModeData (Mnp, NULL, &SnpMode); >>> >>> + if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) { >>> >>> + goto Error; >>> >>> + } >>> >>> + >>> >>> + UnicodeSPrint ( >>> >>> + NicName, >>> >>> + IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH, >>> >>> + SnpMode.IfType == NET_IFTYPE_ETHERNET ? >>> >>> + L"eth%d" : >>> >>> + L"unk%d", >>> >>> + NicNumber >>> >>> + ); >>> >>> + >>> >>> + Status = EFI_SUCCESS; >>> >>> + >>> >>> +Error: >>> >>> + >>> >>> + if (MnpHandle != NULL) { >>> >>> + CloseProtocolAndDestroyServiceChild ( >>> >>> + ControllerHandle, >>> >>> + &gEfiManagedNetworkServiceBindingProtocolGuid, >>> >>> + &gEfiManagedNetworkProtocolGuid, >>> >>> + MnpHandle >>> >>> + ); >>> >>> + } >>> >>> + >>> >>> + return Status; >>> >>> +} >>> >>> + >>> >>> +/** >>> >>> + Create a child for the service identified by its service binding > protocol >> GUID >>> + and get from the child the interface of the protocol identified by > its >> GUID. >>> + >>> >>> + @param[in] ControllerHandle Controller handle. >>> >>> + @param[in] ServiceBindingProtocolGuid Service binding protocol > GUID >> of the >>> + service to be created. >>> >>> + @param[in] ProtocolGuid GUID of the protocol to be > open. >>> + @param[out] ChildHandle Address where the handler > of the >>> + created child is returned. > NULL is >>> + returned in case of error. >>> >>> + @param[out] Interface Address where a pointer to > the >>> + protocol interface is > returned in >>> + case of success. >>> >>> + >>> >>> + @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 = NULL; >>> >>> + Status = NetLibCreateServiceChild ( >>> >>> + ControllerHandle, >>> >>> + gImageHandle, >>> >>> + ServiceBindingProtocolGuid, >>> >>> + ChildHandle >>> >>> + ); >>> >>> + if (!EFI_ERROR (Status)) { >>> >>> + Status = gBS->OpenProtocol ( >>> >>> + *ChildHandle, >>> >>> + ProtocolGuid, >>> >>> + Interface, >>> >>> + gImageHandle, >>> >>> + ControllerHandle, >>> >>> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >>> >>> + ); >>> >>> + if (EFI_ERROR (Status)) { >>> >>> + NetLibDestroyServiceChild ( >>> >>> + ControllerHandle, >>> >>> + gImageHandle, >>> >>> + ServiceBindingProtocolGuid, >>> >>> + *ChildHandle >>> >>> + ); >>> >>> + *ChildHandle = NULL; >>> >>> + } >>> >>> + } >>> >>> + >>> >>> + return Status; >>> >>> +} >>> >>> + >>> >>> +/** >>> >>> + Close the protocol identified by its GUID on the child handle of > the >> service >>> + identified by its service binding protocol GUID, then destroy the > child >>> + handle. >>> >>> + >>> >>> + @param[in] ControllerHandle Controller handle. >>> >>> + @param[in] ServiceBindingProtocolGuid Service binding protocol > GUID >> of the >>> + service to be destroyed. >>> >>> + @param[in] ProtocolGuid GUID of the protocol to be > closed. >>> + @param[in] ChildHandle Handle of the child to be > destroyed. >>> + >>> >>> +**/ >>> >>> +STATIC >>> >>> +VOID >>> >>> +CloseProtocolAndDestroyServiceChild ( >>> >>> + IN EFI_HANDLE ControllerHandle, >>> >>> + IN EFI_GUID *ServiceBindingProtocolGuid, >>> >>> + IN EFI_GUID *ProtocolGuid, >>> >>> + IN EFI_HANDLE ChildHandle >>> >>> + ) >>> >>> +{ >>> >>> + gBS->CloseProtocol ( >>> >>> + ChildHandle, >>> >>> + ProtocolGuid, >>> >>> + gImageHandle, >>> >>> + ControllerHandle >>> >>> + ); >>> >>> + >>> >>> + NetLibDestroyServiceChild ( >>> >>> + ControllerHandle, >>> >>> + gImageHandle, >>> >>> + ServiceBindingProtocolGuid, >>> >>> + ChildHandle >>> >>> + ); >>> >>> +} >>> >>> + >>> >>> +/** >>> >>> + Wait until operation completes. Completion is indicated by >>> >>> + setting of an appropriate variable. >>> >>> + >>> >>> + @param[in] Context A pointer to the HTTP download > context. >>> + @param[in] 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 DOWNLOAD_CONTEXT *Context, >>> >>> + IN OUT BOOLEAN *CallBackComplete >>> >>> + ) >>> >>> +{ >>> >>> + EFI_STATUS Status; >>> >>> + EFI_EVENT WaitEvt; >>> >>> + >>> >>> + Status = EFI_SUCCESS; >>> >>> + >>> >>> + // Use a timer to measure timeout. Cannot use Stall here! >>> >>> + Status = gBS->CreateEvent ( >>> >>> + EVT_TIMER, >>> >>> + TPL_CALLBACK, >>> >>> + NULL, >>> >>> + NULL, >>> >>> + &WaitEvt >>> >>> + ); >>> >>> + ASSERT_EFI_ERROR (Status); >>> >>> + >>> >>> + if (!EFI_ERROR (Status)) { >>> >>> + Status = gBS->SetTimer( >>> >>> + WaitEvt, >>> >>> + TimerRelative, >>> >>> + EFI_TIMER_PERIOD_SECONDS (TIMER_MAX_TIMEOUT_S) >>> >>> + ); >>> >>> + >>> >>> + ASSERT_EFI_ERROR (Status); >>> >>> + } >>> >>> + >>> >>> + while (! *CallBackComplete && >>> >>> + (!EFI_ERROR (Status)) && >>> >>> + EFI_ERROR (gBS->CheckEvent (WaitEvt)) >>> >>> + ) { >>> >>> + Status = Context->Http->Poll (Context->Http); >>> >>> + } >>> >>> + >>> >>> + gBS->SetTimer (WaitEvt, TimerCancel, 0); >>> >>> + gBS->CloseEvent (WaitEvt); >>> >>> + >>> >>> + if (*CallBackComplete) { >>> >>> + return EFI_SUCCESS; >>> >>> + } >>> >>> + >>> >>> + if (!EFI_ERROR (Status)) { >>> >>> + Status = EFI_TIMEOUT; >>> >>> + } >>> >>> + >>> >>> + return Status; >>> >>> +} >>> >>> + >>> >>> +/** >>> >>> + Generate and send a request to the http server. >>> >>> + >>> >>> + @param[in] Context HTTP download context. >>> >>> + @param[in] DownloadUrl Fully qualified URL to be > downloaded. >>> + >>> >>> + @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 DOWNLOAD_CONTEXT *Context, >>> >>> + IN CHAR16 *DownloadUrl >>> >>> + ) >>> >>> +{ >>> >>> + EFI_HTTP_REQUEST_DATA RequestData; >>> >>> + EFI_HTTP_HEADER RequestHeader; >>> >>> + 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.FieldName = "Host"; >>> >>> + >>> >>> + Host = (CHAR16 *)Context->ServerAddrAndProto; >>> >>> + while (*Host != CHAR_NULL && *Host != L'/') { >>> >>> + Host++; >>> >>> + } >>> >>> + >>> >>> + if (*Host == CHAR_NULL) { >>> >>> + return EFI_INVALID_PARAMETER; >>> >>> + } >>> >>> + >>> >>> + // >>> >>> + // Get the next slash >>> >>> + // >>> >>> + Host++; >>> >>> + // >>> >>> + // And now the host name >>> >>> + // >>> >>> + Host++; >>> >>> + >>> >>> + StringSize = StrLen (Host) + 1; >>> >>> + RequestHeader.FieldValue = AllocatePool (StringSize); >>> >>> + if (!RequestHeader.FieldValue) { >>> >>> + return EFI_OUT_OF_RESOURCES; >>> >>> + } >>> >>> + >>> >>> + UnicodeStrToAsciiStrS (Host, RequestHeader.FieldValue, > StringSize); >>> + >>> >>> + RequestMessage.HeaderCount++; >>> >>> + >>> >>> + RequestData.Method = HttpMethodGet; >>> >>> + RequestData.Url = DownloadUrl; >>> >>> + >>> >>> + RequestMessage.Data.Request = &RequestData; >>> >>> + RequestMessage.Headers = &RequestHeader; >>> >>> + RequestMessage.BodyLength = 0; >>> >>> + RequestMessage.Body = NULL; >>> >>> + Context->RequestToken.Event = NULL; >>> >>> + >>> >>> + // >>> >>> + // Completion callback event to be set when Request completes. >>> >>> + // >>> >>> + Status = gBS->CreateEvent ( >>> >>> + EVT_NOTIFY_SIGNAL, >>> >>> + TPL_CALLBACK, >>> >>> + RequestCallback, >>> >>> + Context, >>> >>> + &Context->RequestToken.Event >>> >>> + ); >>> >>> + ASSERT_EFI_ERROR (Status); >>> >>> + >>> >>> + Context->RequestToken.Status = EFI_SUCCESS; >>> >>> + Context->RequestToken.Message = &RequestMessage; >>> >>> + gRequestCallbackComplete = FALSE; >>> >>> + Status = Context->Http->Request (Context->Http, &Context- >>> RequestToken); >>> >>> + if (EFI_ERROR (Status)) { >>> >>> + goto Error; >>> >>> + } >>> >>> + >>> >>> + Status = WaitForCompletion (Context, &gRequestCallbackComplete); >>> >>> + if (EFI_ERROR (Status)) { >>> >>> + Context->Http->Cancel (Context->Http, &Context->RequestToken); >>> >>> + } >>> >>> +Error: >>> >>> + SHELL_FREE_NON_NULL (RequestHeader.FieldValue); >>> >>> + if (Context->RequestToken.Event) { >>> >>> + gBS->CloseEvent (Context->RequestToken.Event); >>> >>> + ZeroMem (&Context->RequestToken, sizeof (Context- >>> RequestToken)); >>> >>> + } >>> >>> + >>> >>> + return Status; >>> >>> +} >>> >>> + >>> >>> +/** >>> >>> + Update the progress of a file download >>> >>> + This procedure is called each time a new HTTP body portion is > received. >>> + >>> >>> + @param[in] Context HTTP download context. >>> >>> + @param[in] DownloadLen Portion size, in bytes. >>> >>> + @param[in] Buffer The pointer to the parsed buffer. >>> >>> + >>> >>> + @retval EFI_SUCCESS Portion saved. >>> >>> + @retval Other Error saving the portion. >>> >>> + >>> >>> +**/ >>> >>> +STATIC >>> >>> +EFI_STATUS >>> >>> +EFIAPI >>> >>> +SavePortion ( >>> >>> + IN DOWNLOAD_CONTEXT *Context, >>> >>> + IN UINTN DownloadLen, >>> >>> + IN CHAR8 *Buffer >>> >>> + ) >>> >>> +{ >>> >>> + CHAR16 Progress[HTTP_PROGRESS_MESSAGE_SIZE]; >>> >>> + UINTN NbOfKb; >>> >>> + UINTN Index; >>> >>> + UINTN LastStep; >>> >>> + UINTN Step; >>> >>> + EFI_STATUS Status; >>> >>> + >>> >>> + LastStep = 0; >>> >>> + Step = 0; >>> >>> + ShellSetFilePosition (mFileHandle, Context->LastReportedNbOfBytes); >>> >>> + Status = ShellWriteFile (mFileHandle, &DownloadLen, Buffer); >>> >>> + if (EFI_ERROR (Status)) { >>> >>> + if (Context->ContentDownloaded > 0) { >>> >>> + ShellPrintHiiEx ( >>> >>> + -1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF), mHttpHiiHandle >>> >>> + ); >>> >>> + } >>> >>> + >>> >>> + ShellPrintHiiEx ( >>> >>> + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_WRITE), >>> >>> + mHttpHiiHandle, mLocalFilePath, Status >>> >>> + ); >>> >>> + >>> >>> + return Status; >>> >>> + } >>> >>> + >>> >>> + if (Context->ContentDownloaded == 0) { >>> >>> + ShellPrintEx (-1, -1, L"%s 0 Kb", HTTP_PROGR_FRAME); >>> >>> + } >>> >>> + >>> >>> + Context->ContentDownloaded += DownloadLen; >>> >>> + NbOfKb = Context->ContentDownloaded >> 10; >>> >>> + >>> >>> + Progress[0] = L'\0'; >>> >>> + if (Context->ContentLength) { >>> >>> + LastStep = (Context->LastReportedNbOfBytes * >>> HTTP_PROGRESS_SLIDER_STEPS) / >>> >>> + Context->ContentLength; >>> >>> + Step = (Context->ContentDownloaded * >> HTTP_PROGRESS_SLIDER_STEPS) / >>> + Context->ContentLength; >>> >>> + } >>> >>> + >>> >>> + Context->LastReportedNbOfBytes = Context->ContentDownloaded; >>> >>> + >>> >>> + if (Step <= LastStep) { >>> >>> + if (!Context->ContentLength) { >>> >>> + // >>> >>> + // Update downloaded size, there is no length info available. >>> >>> + // >>> >>> + ShellPrintEx (-1, -1, L"%s", HTTP_KB); >>> >>> + ShellPrintEx (-1, -1, L"%7d Kb", NbOfKb); >>> >>> + } >>> >>> + >>> >>> + return EFI_SUCCESS; >>> >>> + } >>> >>> + >>> >>> + ShellPrintEx (-1, -1, L"%s", HTTP_PROGRESS_DEL); >>> >>> + >>> >>> + Status = StrCpyS (Progress, HTTP_PROGRESS_MESSAGE_SIZE, >>> HTTP_PROGR_FRAME); >>> >>> + if (EFI_ERROR (Status)) { >>> >>> + return Status; >>> >>> + } >>> >>> + >>> >>> + for (Index = 1; Index < Step; Index++) { >>> >>> + Progress[Index] = L'='; >>> >>> + } >>> >>> + >>> >>> + if (Step) { >>> >>> + Progress[Step] = L'>'; >>> >>> + } >>> >>> + >>> >>> + UnicodeSPrint ( >>> >>> + Progress + (sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) - 1, >>> >>> + sizeof (Progress) - sizeof (HTTP_PROGR_FRAME), >>> >>> + L" %7d Kb", >>> >>> + NbOfKb >>> >>> + ); >>> >>> + >>> >>> + >>> >>> + ShellPrintEx (-1, -1, L"%s", Progress); >>> >>> + >>> >>> + return EFI_SUCCESS; >>> >>> +} >>> >>> + >>> >>> +/** >>> >>> + Replace the original Host and URI with Host and URI returned by the >>> >>> + HTTP server in 'Location' header (redirection). >>> >>> + >>> >>> + @param[in] Location A pointer to the 'Location' string >>> >>> + provided by HTTP server. >>> >>> + @param[in] Context A pointer to HTTP download context. >>> >>> + @param[in] DownloadUrl Fully qualified HTTP URL. >>> >>> + >>> >>> + @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 DOWNLOAD_CONTEXT *Context, >>> >>> + IN CHAR16 *DownloadUrl >>> >>> + ) >>> >>> +{ >>> >>> + EFI_STATUS Status; >>> >>> + UINTN StringSize; >>> >>> + UINTN FirstStep; >>> >>> + UINTN Idx; >>> >>> + UINTN Step; >>> >>> + CHAR8 *Walker; >>> >>> + CHAR16 *Temp; >>> >>> + CHAR8 *Tmp; >>> >>> + CHAR16 *Url; >>> >>> + BOOLEAN IsAbEmptyUrl; >>> >>> + >>> >>> + Tmp = NULL; >>> >>> + Url = NULL; >>> >>> + IsAbEmptyUrl = FALSE; >>> >>> + FirstStep = 0; >>> >>> + >>> >>> + StringSize = (AsciiStrSize (Location) * sizeof (CHAR16)); >>> >>> + Url = AllocateZeroPool (StringSize); >>> >>> + if (!Url) { >>> >>> + return EFI_OUT_OF_RESOURCES; >>> >>> + } >>> >>> + >>> >>> + Status = AsciiStrToUnicodeStrS ( >>> >>> + (CONST CHAR8 *)Location, >>> >>> + Url, >>> >>> + StringSize >>> >>> + ); >>> >>> + >>> >>> + if (EFI_ERROR (Status)) { >>> >>> + goto Error; >>> >>> + } >>> >>> + >>> >>> + // >>> >>> + // If an HTTP server redirects to the same location more than once, >>> >>> + // then stop attempts and tell it is not reachable. >>> >>> + // >>> >>> + if (!StrCmp (Url, DownloadUrl)) { >>> >>> + Status = EFI_NO_MAPPING; >>> >>> + goto Error; >>> >>> + } >>> >>> + >>> >>> + if (AsciiStrLen (Location) > 2) { >>> >>> + // Some servers return 'Location: //server/resource' >>> >>> + IsAbEmptyUrl = (Location[0] == '/') && (Location[1] == '/'); >>> >>> + if (IsAbEmptyUrl) { >>> >>> + // Skip first "//" >>> >>> + Location += 2; >>> >>> + FirstStep = 1; >>> >>> + } >>> >>> + } >>> >>> + >>> >>> + if (AsciiStrStr (Location, "://") || IsAbEmptyUrl) { >>> >>> + Idx = 0; >>> >>> + Walker = Location; >>> >>> + >>> >>> + for (Step = FirstStep; Step < 2; Step++) { >>> >>> + for (; *Walker != '/' && *Walker != '\0'; Walker++) { >>> >>> + Idx++; >>> >>> + } >>> >>> + if (!Step) { >>> >>> + // >>> >>> + // Skip "//" >>> >>> + // >>> >>> + Idx += 2; >>> >>> + Walker += 2; >>> >>> + } >>> >>> + } >>> >>> + >>> >>> + Tmp = AllocateZeroPool (Idx + 1); >>> >>> + if (!Tmp) { >>> >>> + Status = EFI_OUT_OF_RESOURCES; >>> >>> + goto Error; >>> >>> + } >>> >>> + >>> >>> + CopyMem (Tmp, Location, Idx); >>> >>> + >>> >>> + // >>> >>> + // Location now points to URI >>> >>> + // >>> >>> + Location += Idx; >>> >>> + StringSize = (Idx + 1) * sizeof (CHAR16); >>> >>> + >>> >>> + SHELL_FREE_NON_NULL (Context->ServerAddrAndProto); >>> >>> + >>> >>> + Temp = AllocateZeroPool (StringSize); >>> >>> + if (!Temp) { >>> >>> + Status = EFI_OUT_OF_RESOURCES; >>> >>> + goto Error; >>> >>> + } >>> >>> + >>> >>> + Status = AsciiStrToUnicodeStrS ( >>> >>> + (CONST CHAR8 *)Tmp, >>> >>> + Temp, >>> >>> + StringSize >>> >>> + ); >>> >>> + if (EFI_ERROR (Status)) { >>> >>> + SHELL_FREE_NON_NULL (Temp); >>> >>> + goto Error; >>> >>> + } >>> >>> + >>> >>> + Idx = 0; >>> >>> + if (IsAbEmptyUrl) { >>> >>> + Context->ServerAddrAndProto = StrnCatGrow ( >>> >>> + &Context->ServerAddrAndProto, >>> >>> + &Idx, >>> >>> + L"http://", >>> >>> + StrLen (L"http://") >>> >>> + ); >>> >>> + } >>> >>> + >>> >>> + Context->ServerAddrAndProto = StrnCatGrow ( >>> >>> + &Context->ServerAddrAndProto, >>> >>> + &Idx, >>> >>> + Temp, >>> >>> + StrLen (Temp) >>> >>> + ); >>> >>> + SHELL_FREE_NON_NULL (Temp); >>> >>> + if (!Context->ServerAddrAndProto) { >>> >>> + Status = EFI_OUT_OF_RESOURCES; >>> >>> + goto Error; >>> >>> + } >>> >>> + } >>> >>> + >>> >>> + SHELL_FREE_NON_NULL (Context->URI); >>> >>> + >>> >>> + StringSize = AsciiStrSize (Location) * sizeof (CHAR16); >>> >>> + Context->URI = AllocateZeroPool (StringSize); >>> >>> + if (!Context->URI) { >>> >>> + Status = EFI_OUT_OF_RESOURCES; >>> >>> + goto Error; >>> >>> + } >>> >>> + >>> >>> + // >>> >>> + // Now make changes to the URI part. >>> >>> + // >>> >>> + Status = AsciiStrToUnicodeStrS ( >>> >>> + (CONST CHAR8 *)Location, >>> >>> + Context->URI, >>> >>> + StringSize >>> >>> + ); >>> >>> +Error: >>> >>> + SHELL_FREE_NON_NULL (Tmp); >>> >>> + SHELL_FREE_NON_NULL (Url); >>> >>> + return Status; >>> >>> +} >>> >>> + >>> >>> +/** >>> >>> + Message parser callback. >>> >>> + Save a portion of HTTP body. >>> >>> + >>> >>> + @param[in] EventType Type of event. Can be either >>> >>> + OnComplete or OnData. >>> >>> + @param[in] Data A pointer to the buffer with data. >>> >>> + @param[in] Length Data length of this portion. >>> >>> + @param[in] Context A pointer to the HTTP download > context. >>> + >>> >>> + @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 == 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 > the >>> + HTTP server >>> >>> + indicated an error (HTTP code >= 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 DOWNLOAD_CONTEXT *Context, >>> >>> + IN CHAR16 *DownloadUrl >>> >>> + ) >>> >>> +{ >>> >>> + EFI_HTTP_RESPONSE_DATA ResponseData; >>> >>> + EFI_HTTP_MESSAGE ResponseMessage; >>> >>> + EFI_HTTP_HEADER *Header; >>> >>> + EFI_STATUS Status; >>> >>> + VOID *MsgParser; >>> >>> + CONST CHAR16 *Desc; >>> >>> + BOOLEAN IsTrunked; >>> >>> + BOOLEAN Redirection; >>> >>> + >>> >>> + ZeroMem (&ResponseData, sizeof (ResponseData)); >>> >>> + ZeroMem (&ResponseMessage, sizeof (ResponseMessage)); >>> >>> + ZeroMem (&Context->ResponseToken, sizeof (Context- >>> ResponseToken)); >>> >>> + IsTrunked = FALSE; >>> >>> + >>> >>> + ResponseMessage.Body = Context->Buffer; >>> >>> + Context->ResponseToken.Status = EFI_SUCCESS; >>> >>> + Context->ResponseToken.Message = &ResponseMessage; >>> >>> + Context->ContentLength = 0; >>> >>> + Context->Status = REQ_OK; >>> >>> + MsgParser = NULL; >>> >>> + ResponseData.StatusCode = HTTP_STATUS_UNSUPPORTED_STATUS; >>> >>> + ResponseMessage.Data.Response = &ResponseData; >>> >>> + Context->ResponseToken.Event = NULL; >>> >>> + >>> >>> + do { >>> >>> + SHELL_FREE_NON_NULL (ResponseMessage.Headers); >>> >>> + ResponseMessage.HeaderCount = 0; >>> >>> + gResponseCallbackComplete = FALSE; >>> >>> + ResponseMessage.BodyLength = Context->BufferSize; >>> >>> + >>> >>> + if (ShellGetExecutionBreakFlag ()) { >>> >>> + Status = EFI_ABORTED; >>> >>> + break; >>> >>> + } >>> >>> + >>> >>> + if (!Context->ContentDownloaded && !Context- >>> ResponseToken.Event) { >>> >>> + Status = gBS->CreateEvent ( >>> >>> + EVT_NOTIFY_SIGNAL, >>> >>> + TPL_CALLBACK, >>> >>> + ResponseCallback, >>> >>> + Context, >>> >>> + &Context->ResponseToken.Event >>> >>> + ); >>> >>> + ASSERT_EFI_ERROR (Status); >>> >>> + } else { >>> >>> + ResponseMessage.Data.Response = NULL; >>> >>> + } >>> >>> + >>> >>> + if (EFI_ERROR (Status)) { >>> >>> + break; >>> >>> + } >>> >>> + >>> >>> + Status = Context->Http->Response (Context->Http, &Context- >>>> ResponseToken); >>> + if (EFI_ERROR (Status)) { >>> >>> + break; >>> >>> + } >>> >>> + >>> >>> + Status = WaitForCompletion (Context, &gResponseCallbackComplete); >>> >>> + if (EFI_ERROR (Status) && ResponseMessage.HeaderCount) { >>> >>> + Status = EFI_SUCCESS; >>> >>> + } >>> >>> + >>> >>> + if (EFI_ERROR (Status)) { >>> >>> + Context->Http->Cancel (Context->Http, &Context->ResponseToken); >>> >>> + break; >>> >>> + } >>> >>> + >>> >>> + if (!Context->ContentDownloaded) { >>> >>> + Redirection = >>> >>> + ((ResponseData.StatusCode >= >> HTTP_STATUS_300_MULTIPLE_CHOICES) >>> && >>> >>> + (ResponseData.StatusCode <= >>> HTTP_STATUS_307_TEMPORARY_REDIRECT) >>> >>> + ) || >>> >>> + (ResponseData.StatusCode == >>> HTTP_STATUS_308_PERMANENT_REDIRECT); >>> >>> + >>> >>> + if (Redirection) { >>> >>> + // >>> >>> + // Need to repeat the request with new Location (server > redirected). >>> + // >>> >>> + Context->Status = REQ_NEED_REPEAT; >>> >>> + >>> >>> + Header = HttpFindHeader ( >>> >>> + ResponseMessage.HeaderCount, >>> >>> + ResponseMessage.Headers, >>> >>> + "Location" >>> >>> + ); >>> >>> + if (Header) { >>> >>> + Status = SetHostURI (Header->FieldValue, Context, > DownloadUrl); >>> + if (Status == EFI_NO_MAPPING) { >>> >>> + ShellPrintHiiEx ( >>> >>> + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_STATUSCODE), >>> >>> + mHttpHiiHandle, Context->ServerAddrAndProto, >>> >>> + L"Recursive HTTP server relocation", >>> >>> + Context->URI >>> >>> + ); >>> >>> + } >>> >>> + } else { >>> >>> + // >>> >>> + // Bad reply from the server. Server must specify the > location. >>> + // Indicate that resource was not found, and no body > collected. >>> + // >>> >>> + Status = EFI_NOT_FOUND; >>> >>> + } >>> >>> + >>> >>> + Context->Http->Cancel (Context->Http, > &Context->ResponseToken); >>> + break; >>> >>> + } >>> >>> + >>> >>> + // >>> >>> + // Init message-body parser by header information. >>> >>> + // >>> >>> + if (!MsgParser) { >>> >>> + Status = HttpInitMsgParser ( >>> >>> + ResponseMessage.Data.Request->Method, >>> >>> + ResponseData.StatusCode, >>> >>> + ResponseMessage.HeaderCount, >>> >>> + ResponseMessage.Headers, >>> >>> + ParseMsg, >>> >>> + Context, >>> >>> + &MsgParser >>> >>> + ); >>> >>> + if (EFI_ERROR (Status)) { >>> >>> + break; >>> >>> + } >>> >>> + } >>> >>> + >>> >>> + // >>> >>> + // If it is a trunked message, rely on the parser. >>> >>> + // >>> >>> + Header = HttpFindHeader ( >>> >>> + ResponseMessage.HeaderCount, >>> >>> + ResponseMessage.Headers, >>> >>> + "Transfer-Encoding" >>> >>> + ); >>> >>> + IsTrunked = (Header && !AsciiStrCmp (Header->FieldValue, >> "chunked")); >>> + >>> >>> + HttpGetEntityLength (MsgParser, &Context->ContentLength); >>> >>> + >>> >>> + if (ResponseData.StatusCode >= HTTP_STATUS_400_BAD_REQUEST >> && >>> + (ResponseData.StatusCode != >>> HTTP_STATUS_308_PERMANENT_REDIRECT) >>> >>> + ) { >>> >>> + // >>> >>> + // Server reported an error via Response code. >>> >>> + // Collect the body if any. >>> >>> + // >>> >>> + if (!gHttpError) { >>> >>> + gHttpError = TRUE; >>> >>> + >>> >>> + Desc = ErrStatusDesc[ResponseData.StatusCode - >>> >>> + HTTP_STATUS_400_BAD_REQUEST]; >>> >>> + ShellPrintHiiEx ( >>> >>> + -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_STATUSCODE), >>> >>> + mHttpHiiHandle, Context->ServerAddrAndProto, >>> >>> + Desc, >>> >>> + Context->URI >>> >>> + ); >>> >>> + >>> >>> + // >>> >>> + // This gives an RFC HTTP error. >>> >>> + // >>> >>> + Context->Status = ShellStrToUintn (Desc); >>> >>> + } >>> >>> + } >>> >>> + } >>> >>> + >>> >>> + // Do NOT try to parse an empty body. >>> >>> + if (ResponseMessage.BodyLength || IsTrunked) { >>> >>> + Status = HttpParseMessageBody ( >>> >>> + MsgParser, >>> >>> + ResponseMessage.BodyLength, >>> >>> + ResponseMessage.Body >>> >>> + ); >>> >>> + } >>> >>> + } while (!HttpIsMessageComplete (MsgParser) && >>> >>> + !EFI_ERROR (Status) && >>> >>> + ResponseMessage.BodyLength >>> >>> + ); >>> >>> + >>> >>> + 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. >>> + >>> >>> + @retval EFI_SUCCESS The file was downloaded. >>> >>> + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. >>> >>> + #retval EFI_HTTP_ERROR The server returned a valid HTTP > error. >>> + Examine the mLocalFilePath file >>> >>> + to get error body. >>> >>> + @retval Others The downloading of the file from the > server >>> + failed. >>> >>> + >>> >>> +**/ >>> >>> +STATIC >>> >>> +EFI_STATUS >>> >>> +DownloadFile ( >>> >>> + IN DOWNLOAD_CONTEXT *Context >>> >>> + ) >>> >>> +{ >>> >>> + EFI_STATUS Status; >>> >>> + CHAR16 *DownloadUrl; >>> >>> + UINTN UrlSize; >>> >>> + >>> >>> + ASSERT (Context); >>> >>> + if (!Context) { >>> >>> + return EFI_INVALID_PARAMETER; >>> >>> + } >>> >>> + >>> >>> + DownloadUrl = NULL; >>> >>> + >>> >>> + Context->Buffer = AllocatePool (Context->BufferSize); >>> >>> + if (!Context->Buffer) { >>> >>> + Status = EFI_OUT_OF_RESOURCES; >>> >>> + goto ON_EXIT; >>> >>> + } >>> >>> + >>> >>> + // >>> >>> + // OPEN FILE >>> >>> + // >>> >>> + if (!EFI_ERROR (ShellFileExists (mLocalFilePath))) { >>> >>> + ShellDeleteFileByName (mLocalFilePath); >>> >>> + } >>> >>> + >>> >>> + Status = ShellOpenFileByName ( >>> >>> + mLocalFilePath, >>> >>> + &mFileHandle, >>> >>> + EFI_FILE_MODE_CREATE | >>> >>> + EFI_FILE_MODE_WRITE | >>> >>> + EFI_FILE_MODE_READ, >>> >>> + 0); >>> >>> + if (EFI_ERROR (Status)) { >>> >>> + ShellPrintHiiEx ( >>> >>> + -1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), >>> >>> + mHttpHiiHandle, HTTP_APP_NAME, mLocalFilePath >>> >>> + ); >>> >>> + goto ON_EXIT; >>> >>> + } >>> >>> + >>> >>> + do { >>> >>> + SHELL_FREE_NON_NULL (DownloadUrl); >>> >>> + UrlSize = 0; >>> >>> + DownloadUrl = StrnCatGrow ( >>> >>> + &DownloadUrl, >>> >>> + &UrlSize, >>> >>> + Context->ServerAddrAndProto, >>> >>> + StrLen (Context->ServerAddrAndProto) >>> >>> + ); >>> >>> + if (Context->URI[0] != L'/') { >>> >>> + DownloadUrl = StrnCatGrow ( >>> >>> + &DownloadUrl, >>> >>> + &UrlSize, >>> >>> + L"/", >>> >>> + StrLen (Context->ServerAddrAndProto) >>> >>> + ); >>> >>> + } >>> >>> + >>> >>> + DownloadUrl = StrnCatGrow ( >>> >>> + &DownloadUrl, >>> >>> + &UrlSize, >>> >>> + Context->URI, >>> >>> + StrLen (Context->URI)); >>> >>> + >>> >>> + ShellPrintHiiEx ( >>> >>> + -1, -1, NULL, STRING_TOKEN (STR_HTTP_DOWNLOADING), >>> >>> + mHttpHiiHandle, DownloadUrl); >>> >>> + >>> >>> + Status = SendRequest (Context, DownloadUrl); >>> >>> + if (Status) { >>> >>> + goto ON_EXIT; >>> >>> + } >>> >>> + >>> >>> + Status = GetResponse (Context, DownloadUrl); >>> >>> + >>> >>> + if (Status) { >>> >>> + goto ON_EXIT; >>> >>> + } >>> >>> + >>> >>> + } while (Context->Status == REQ_NEED_REPEAT); >>> >>> + >>> >>> + if (Context->Status) { >>> >>> + Status = ENCODE_ERROR (Context->Status); >>> >>> + } >>> >>> + >>> >>> +ON_EXIT: >>> >>> + // >>> >>> + // CLOSE 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); >>> >>> + >>> >>> + 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 = gBS->OpenProtocol ( >>> >>> + ImageHandle, >>> >>> + &gEfiHiiPackageListProtocolGuid, >>> >>> + (VOID **)&PackageList, >>> >>> + ImageHandle, >>> >>> + NULL, >>> >>> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >>> >>> + ); >>> >>> + ASSERT_EFI_ERROR (Status); >>> >>> + if (EFI_ERROR (Status)) { >>> >>> + return NULL; >>> >>> + } >>> >>> + >>> >>> + // >>> >>> + // Publish HII package list to HII Database. >>> >>> + // >>> >>> + Status = gHiiDatabase->NewPackageList ( >>> >>> + gHiiDatabase, >>> >>> + PackageList, >>> >>> + NULL, >>> >>> + &HiiHandle >>> >>> + ); >>> >>> + ASSERT_EFI_ERROR (Status); >>> >>> + if (EFI_ERROR (Status)) { >>> >>> + return NULL; >>> >>> + } >>> >>> + >>> >>> + return HiiHandle; >>> >>> +} >>> >>> diff --git a/ShellPkg/DynamicCommand/HttpDynamicCommand/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 >>> >>> + 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; >>> >>> +} 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/DynamicCommand/HttpDynamicCommand/Http.uni >>> b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni >>> new file mode 100644 >>> index 000000000000..00cf05deeb5c >>> --- /dev/null >>> +++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni >>> @@ -0,0 +1,117 @@ >>> +// /** >>> >>> +// >>> >>> +// (C) Copyright 2015-2016 Hewlett Packard Enterprise Development >> LP
>>> +// Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved. >
>>> +// Copyright (c) 2020, Broadcom. All rights reserved.
>>> >>> +// SPDX-License-Identifier: BSD-2-Clause-Patent >>> >>> +// >>> >>> +// Module Name: >>> >>> +// >>> >>> +// Http.uni >>> >>> +// >>> >>> +// Abstract: >>> >>> +// >>> >>> +// String definitions for UEFI Shell HTTP command >>> >>> +// >>> >>> +// >>> >>> +// **/ >>> >>> + >>> >>> +/=# >>> >>> + >>> >>> +#langdef en-US "english" >>> >>> + >>> >>> +#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too >> many >>> arguments. Try help http.\r\n" >>> >>> +#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few >>> arguments. Try help http.\r\n" >>> >>> +#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid >>> argument - '%H%s%N'. Try help http.\r\n" >>> >>> +#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown >> flag - >>> '%H%s%N'. Try help http.\r\n" >>> >>> +#string STR_GEN_FILE_OPEN_FAIL #language en-US "%H%s%N: Cannot >> open >>> file - '%H%s%N'\r\n" >>> >>> +#string STR_GEN_CRLF #language en-US "\r\n" >>> >>> + >>> >>> +#string STR_HTTP_ERR_NO_NIC #language en-US "No network >> interface >>> card found.\r\n" >>> >>> +#string STR_HTTP_ERR_NIC_NAME #language en-US "Failed to get the >> name >>> of the network interface card number %d - %r\r\n" >>> >>> +#string STR_HTTP_ERR_OPEN_PROTOCOL #language en-US "Unable to >> open >>> HTTP protocol on '%H%s%N' - %r\r\n" >>> >>> +#string STR_HTTP_ERR_CONFIGURE #language en-US "Unable to >> configure >>> HTTP protocol on '%H%s%N' - %r\r\n" >>> >>> +#string STR_HTTP_ERR_DOWNLOAD #language en-US "Unable to >> download >>> the file '%H%s%N' on '%H%s%N' - %r\r\n" >>> >>> +#string STR_HTTP_ERR_WRITE #language en-US "Unable to write > into >> file >>> '%H%s%N' - %r\r\n" >>> >>> +#string STR_HTTP_ERR_NIC_NOT_FOUND #language en-US "Network >> Interface >>> Card '%H%s%N' not found.\r\n" >>> >>> +#string STR_HTTP_ERR_STATUSCODE #language en-US "\r'%H%s%N' >> reports >>> '%s' for '%H%s%N' \r\n" >>> >>> +#string STR_HTTP_DOWNLOADING #language en-US "Downloading >>> '%H%s%N'\r\n" >>> >>> + >>> >>> +#string STR_GET_HELP_HTTP #language en-US "" >>> >>> +".TH http 0 "Download a file from HTTP server."\r\n" >>> >>> +".SH NAME\r\n" >>> >>> +"Download a file from HTTP server.\r\n" >>> >>> +".SH SYNOPSIS\r\n" >>> >>> +" \r\n" >>> >>> +"HTTP [-i interface] [-l port] [-t timeout] [-s size] [-m] [-k]\r\n" >>> >>> +" [localfilepath]\r\n" >>> >>> +".SH OPTIONS\r\n" >>> >>> +" \r\n" >>> >>> +" -i interface - Specifies an adapter name, i.e., eth0.\r\n" >>> >>> +" -k Keep the downloaded file even if there was an > error.\r\n" >>> +" If this parameter is not used, the file will be > deleted.\r\n" >>> +" -l port - Specifies the local port number. Default value > is 0\r\n" >>> +" and the port number is automatically > assigned.\r\n" >>> +" -m Measure and report download time (in seconds). > \r\n" >>> +" -s size The size of the download buffer for a chunk, in > bytes.\r\n" >>> +" Default is 32K. Note that larger buffer does > not imply\r\n" >>> +" better speed.\r\n" >>> >>> +" -t timeout - The number of seconds to wait for completion > of\r\n" >>> +" requests and responses. Default is 0 which is > 'automatic'.\r\n" >>> +" %HURL%N\r\n" >>> >>> +" Two types of providing of URLs are supported:\r\n" >>> >>> +" 1. tftp-like, where host and http_uri are separate > parameters\r\n" >>> +" (example: host /host_uri), and\r\n\" >>> >>> +" 2. wget-like, where host and host_uri is one parameter.\r\n" >>> >>> +" (example: host/host_uri)\r\n" >>> >>> +"\r\n" >>> >>> +" host - Specifies HTTP Server address.\r\n >>> >>> + Can be either IPv4 address or 'http (or > https)://addr'\r\n >>> + Can use addresses resolvable by DNS as well. > \r\n >>> + Port can be specified after ':' if needed. > \r\n >>> + By default port 80 is used.\r\n" >>> >>> +" http_uri - HTTP server URI to download the file.\r\n" >>> >>> +"\r\n" >>> >>> +" localfilepath - Local destination file path.\r\n" >>> >>> +".SH DESCRIPTION\r\n" >>> >>> +" \r\n" >>> >>> +"NOTES:\r\n" >>> >>> +" 1. The HTTP command allows geting of the file specified by its >> 'http_uri'\r\n" >>> +" path from the HTTP server specified by its 'host' IPv4 address. > If >> the\r\n" >>> +" optional 'localfilepath' parameter is provided, the downloaded > file >> is\r\n" >>> +" stored locally using the provided file path. If the local file > path is\r\n" >>> +" not specified, the file is stored in the current directory > using the >> file\r\n" >>> +" server's name.\r\n" >>> >>> +" 2. Before using the HTTP command, the network interface intended > to >>> be\r\n" >>> >>> +" used to retrieve the file must be configured. This > configuration may >> be\r\n" >>> +" done by means of the 'ifconfig' command.\r\n" >>> >>> +" 3. If a network interface is defined with the '-i' option then > only >> this\r\n" >>> +" interface will be used to retrieve the remote file. Otherwise, > all >>> network\r\n" >>> >>> +" interfaces are tried in the order they have been discovered > during >> the\r\n" >>> +" DXE phase.\r\n" >>> >>> +".SH EXAMPLES\r\n" >>> >>> +" \r\n" >>> >>> +"EXAMPLES:\r\n" >>> >>> +" * To get the file "dir1/file1.dat" from the HTTP server > 192.168.1.1, port >> 8080, >>> and\r\n" >>> >>> +" store it as file2.dat in the current directory (use tftp-like > URL format) >> :\r\n" >>> +" fs0:\> http 192.168.1.1:8080 dir1/file1.dat file2.dat\r\n" >>> >>> +" * To get the file /image.bin via HTTPS from server 192.168.1.1 at > port 443 >>> \r\n" >>> >>> +" (default HTTPS port), and store it in the current directory: > \r\n" >>> +" fs0:\> http https://192.168.1.1 image.bin\r\n" >>> >>> +" To get an index file from http://google.com and place it into > the \r\n" >>> +" current directory:\r\n" >>> >>> +" fs0:\> http google.com index.html\r\n" >>> >>> +".SH RETURNVALUES\r\n" >>> >>> +" \r\n" >>> >>> +"RETURN VALUES:\r\n" >>> >>> +" SHELL_SUCCESS The action was completed as > requested.\r\n" >>> +" SHELL_INVALID_PARAMETER One of the passed-in parameters was >>> incorrectly\r\n" >>> >>> +" formatted or its value was out of > bounds.\r\n" >>> +" HTTP_ERROR No EFI errors, but the server reported a > status >>> code\r\n" >>> >>> +" which should be treated as an error. If > an error body >> sent\r\n" >>> +" by the server, and -k parameter is on > command line, >>> +" the file wil be saved either as > localfilepath filename,\r\n" >>> +" or as an URI name in the current > directory.\r\n" >>> +" If '/' is at the end of the URL, and no > locafilepath >> filename\r\n" >>> +" is given on the command line, the file > will be retrieved >> as\r\n" >>> +" index.html.\r\n" >>> >>> 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 >>> >>> + Entrypoint of "http" shell standalone application. >>> >>> + >>> >>> + Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved. >
>>> + Copyright (c) 2015, ARM Ltd. All rights reserved.
>>> >>> + Copyright (c) 2020, Broadcom. All rights reserved.
>>> >>> + >>> >>> + SPDX-License-Identifier: BSD-2-Clause-Patent >>> >>> + >>> >>> +**/ >>> >>> +#include "Http.h" >>> >>> + >>> >>> +/* >>> >>> + * String token ID of help message text. >>> >>> + * Shell supports to find help message in the resource section of an >>> >>> + * application image if * .MAN file is not found. >>> >>> + * This global variable is added to make build tool recognizes >>> >>> + * that the help string is consumed by user and then build tool will >>> >>> + * add the string into the resource section. >>> >>> + * Thus the application can use '-?' option to show help message in > Shell. >>> + */ >>> >>> +GLOBAL_REMOVE_IF_UNREFERENCED >>> >>> +EFI_STRING_ID mStringHelpTokenId = STRING_TOKEN >> (STR_GET_HELP_HTTP); >>> + >>> >>> +/** >>> >>> + Entry point of Http standalone application. >>> >>> + >>> >>> + @param ImageHandle The image handle of the process. >>> >>> + @param SystemTable The EFI System Table pointer. >>> >>> + >>> >>> + @retval EFI_SUCCESS Http command is executed sucessfully. >>> >>> + @retval EFI_ABORTED HII package was failed to initialize. >>> >>> + @retval others Other errors when executing http > command. >>> +**/ >>> >>> +EFI_STATUS >>> >>> +EFIAPI >>> >>> +HttpAppInitialize ( >>> >>> + IN EFI_HANDLE ImageHandle, >>> >>> + IN EFI_SYSTEM_TABLE *SystemTable >>> >>> + ) >>> >>> +{ >>> >>> + EFI_STATUS Status; >>> >>> + mHttpHiiHandle = InitializeHiiPackage (ImageHandle); >>> >>> + if (mHttpHiiHandle == NULL) { >>> >>> + return EFI_ABORTED; >>> >>> + } >>> >>> + >>> >>> + Status = (EFI_STATUS)RunHttp (ImageHandle, SystemTable); >>> >>> + >>> >>> + HiiRemovePackages (mHttpHiiHandle); >>> >>> + >>> >>> + return Status; >>> >>> +} >>> >>> 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 = 0x00010006 >>> >>> + BASE_NAME = http >>> >>> + FILE_GUID = > 56B00FB7-91D2-869B-CE5C-26CD1A89C73C >>> + MODULE_TYPE = UEFI_APPLICATION >>> >>> + VERSION_STRING = 1.0 >>> >>> + ENTRY_POINT = HttpAppInitialize >>> >>> +# >>> >>> +# This flag specifies whether HII resource section is generated into > PE >> image. >>> +# >>> >>> + UEFI_HII_RESOURCE_SECTION = TRUE >>> >>> + >>> >>> +[Sources.common] >>> >>> + Http.c >>> >>> + HttpApp.c >>> >>> + Http.h >>> >>> + Http.uni >>> >>> + >>> >>> +[Packages] >>> >>> + EmbeddedPkg/EmbeddedPkg.dec >>> >>> + MdeModulePkg/MdeModulePkg.dec >>> >>> + MdePkg/MdePkg.dec >>> >>> + NetworkPkg/NetworkPkg.dec >>> >>> + ShellPkg/ShellPkg.dec >>> >>> + >>> >>> +[LibraryClasses] >>> >>> + BaseLib >>> >>> + BaseMemoryLib >>> >>> + DebugLib >>> >>> + FileHandleLib >>> >>> + HiiLib >>> >>> + HttpLib >>> >>> + MemoryAllocationLib >>> >>> + NetLib >>> >>> + ShellLib >>> >>> + UefiApplicationEntryPoint >>> >>> + UefiBootServicesTableLib >>> >>> + UefiHiiServicesLib >>> >>> + UefiLib >>> >>> + UefiRuntimeServicesTableLib >>> >>> + >>> >>> +[Protocols] >>> >>> + gEfiHiiPackageListProtocolGuid ## CONSUMES >>> >>> + gEfiHttpProtocolGuid ## CONSUMES >>> >>> + gEfiHttpServiceBindingProtocolGuid ## CONSUMES >>> >>> + gEfiManagedNetworkServiceBindingProtocolGuid ## CONSUMES >>> >>> diff --git >>> >> a/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma >> nd.c >> b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma >> nd.c >>> new file mode 100644 >>> index 000000000000..ba654749a075 >>> --- /dev/null >>> +++ >>> >> b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma >> nd.c >>> @@ -0,0 +1,134 @@ >>> +/** @file >>> >>> + Produce "http" shell dynamic command. >>> >>> + >>> >>> + Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved. >
>>> + Copyright (c) 2015, ARM Ltd. All rights reserved.
>>> >>> + Copyright (c) 2020, Broadcom. All rights reserved.
>>> >>> + >>> >>> + SPDX-License-Identifier: BSD-2-Clause-Patent >>> >>> + >>> >>> +**/ >>> >>> +#include >>> >>> +#include "Http.h" >>> >>> + >>> >>> +/** >>> >>> + This is the shell command handler function pointer callback type. > This >>> + function handles the command when it is invoked in the shell. >>> >>> + >>> >>> + @param[in] This The instance of the >>> >>> + EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. >>> >>> + @param[in] SystemTable The pointer to the system table. >>> >>> + @param[in] ShellParameters The parameters associated with the >> command. >>> + @param[in] Shell The instance of the shell protocol > used in >>> + the context of processing this > command. >>> + >>> >>> + @return EFI_SUCCESS the operation was sucessful >>> >>> + @return other the operation failed. >>> >>> +**/ >>> >>> +SHELL_STATUS >>> >>> +EFIAPI >>> >>> +HttpCommandHandler ( >>> >>> + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, >>> >>> + IN EFI_SYSTEM_TABLE *SystemTable, >>> >>> + IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, >>> >>> + IN EFI_SHELL_PROTOCOL *Shell >>> >>> + ) >>> >>> +{ >>> >>> + gEfiShellParametersProtocol = ShellParameters; >>> >>> + gEfiShellProtocol = Shell; >>> >>> + >>> >>> + return RunHttp (gImageHandle, SystemTable); >>> >>> +} >>> >>> + >>> >>> +/** >>> >>> + This is the command help handler function pointer callback type. > This >>> + function is responsible for displaying help information for the > associated >>> + command. >>> >>> + >>> >>> + @param[in] This The instance of the >>> EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. >>> >>> + @param[in] Language The pointer to the language string to use. >>> >>> + >>> >>> + @return string Pool allocated help string, must be freed by > caller >>> +**/ >>> >>> +CHAR16 * >>> >>> +EFIAPI >>> >>> +HttpCommandGetHelp ( >>> >>> + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, >>> >>> + IN CONST CHAR8 *Language >>> >>> + ) >>> >>> +{ >>> >>> + return HiiGetString(mHttpHiiHandle, >>> >>> + STRING_TOKEN (STR_GET_HELP_HTTP), >>> >>> + Language); >>> >>> +} >>> >>> + >>> >>> +EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mHttpDynamicCommand >> = { >>> + HTTP_APP_NAME, >>> >>> + HttpCommandHandler, >>> >>> + HttpCommandGetHelp >>> >>> +}; >>> >>> + >>> >>> +/** >>> >>> + Entry point of Http Dynamic Command. >>> >>> + >>> >>> + Produce the DynamicCommand protocol to handle "http" command. >>> >>> + >>> >>> + @param ImageHandle The image handle of the process. >>> >>> + @param SystemTable The EFI System Table pointer. >>> >>> + >>> >>> + @retval EFI_SUCCESS Http command is executed sucessfully. >>> >>> + @retval EFI_ABORTED HII package was failed to initialize. >>> >>> + @retval others Other errors when executing http > command. >>> +**/ >>> >>> +EFI_STATUS >>> >>> +EFIAPI >>> >>> +HttpCommandInitialize ( >>> >>> + IN EFI_HANDLE ImageHandle, >>> >>> + IN EFI_SYSTEM_TABLE *SystemTable >>> >>> + ) >>> >>> +{ >>> >>> + EFI_STATUS Status; >>> >>> + >>> >>> + mHttpHiiHandle = InitializeHiiPackage (ImageHandle); >>> >>> + if (mHttpHiiHandle == NULL) { >>> >>> + return EFI_ABORTED; >>> >>> + } >>> >>> + >>> >>> + Status = gBS->InstallProtocolInterface ( >>> >>> + &ImageHandle, >>> >>> + &gEfiShellDynamicCommandProtocolGuid, >>> >>> + EFI_NATIVE_INTERFACE, >>> >>> + &mHttpDynamicCommand >>> >>> + ); >>> >>> + ASSERT_EFI_ERROR (Status); >>> >>> + return Status; >>> >>> +} >>> >>> + >>> >>> +/** >>> >>> + Http driver unload handler. >>> >>> + >>> >>> + @param ImageHandle The image handle of the process. >>> >>> + >>> >>> + @retval EFI_SUCCESS The image is unloaded. >>> >>> + @retval Others Failed to unload the image. >>> >>> +**/ >>> >>> +EFI_STATUS >>> >>> +EFIAPI >>> >>> +HttpUnload ( >>> >>> + IN EFI_HANDLE ImageHandle >>> >>> +) >>> >>> +{ >>> >>> + EFI_STATUS Status; >>> >>> + Status = gBS->UninstallProtocolInterface ( >>> >>> + ImageHandle, >>> >>> + &gEfiShellDynamicCommandProtocolGuid, >>> >>> + &mHttpDynamicCommand >>> >>> + ); >>> >>> + if (EFI_ERROR (Status)) { >>> >>> + return Status; >>> >>> + } >>> >>> + >>> >>> + HiiRemovePackages (mHttpHiiHandle); >>> >>> + >>> >>> + return EFI_SUCCESS; >>> >>> +} >>> >>> diff --git >>> >> a/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma >> nd.in >>> f >>> >> b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma >> nd.in >>> f >>> new file mode 100644 >>> index 000000000000..5d46ee2384d5 >>> --- /dev/null >>> +++ >>> >> b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma >> nd.in >>> f >>> @@ -0,0 +1,63 @@ >>> +## @file >>> >>> +# Provides Shell 'http' dynamic command. >>> >>> +# >>> >>> +# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved. >
>>> +# Copyright (c) 2015, ARM Ltd. All rights reserved.
>>> >>> +# Copyright (c) 2020, Broadcom. All rights reserved.
>>> >>> +# >>> >>> +# SPDX-License-Identifier: BSD-2-Clause-Patent >>> >>> +# >>> >>> +# >>> >>> +## >>> >>> + >>> >>> +[Defines] >>> >>> + INF_VERSION = 0x00010006 >>> >>> + BASE_NAME = httpDynamicCommand >>> >>> + FILE_GUID = > 19618BCE-55AE-09C6-37E9-4CE04084C7A1 >>> + MODULE_TYPE = DXE_DRIVER >>> >>> + VERSION_STRING = 1.0 >>> >>> + ENTRY_POINT = HttpCommandInitialize >>> >>> + UNLOAD_IMAGE = HttpUnload >>> >>> +# >>> >>> +# This flag specifies whether HII resource section is generated into > PE >> image. >>> +# >>> >>> + UEFI_HII_RESOURCE_SECTION = TRUE >>> >>> + >>> >>> +[Sources.common] >>> >>> + Http.c >>> >>> + HttpDynamicCommand.c >>> >>> + Http.h >>> >>> + Http.uni >>> >>> + >>> >>> +[Packages] >>> >>> + 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/Include/Guid/ShellLibHiiGuid.h >>> b/ShellPkg/Include/Guid/ShellLibHiiGuid.h >>> index 5da9128333a4..6e328b460d8c 100644 >>> --- a/ShellPkg/Include/Guid/ShellLibHiiGuid.h >>> +++ b/ShellPkg/Include/Guid/ShellLibHiiGuid.h >>> @@ -59,6 +59,10 @@ >>> 0x738a9314, 0x82c1, 0x4592, { 0x8f, 0xf7, 0xc1, 0xbd, 0xf1, 0xb2, > 0x0e, >> 0xd4 } >>> \ >>> >>> } >>> >>> >>> >>> +#define SHELL_HTTP_HII_GUID \ >>> >>> + { \ >>> >>> + 0x390f84b3, 0x221c, 0x4d9e, { 0xb5, 0x06, 0x6d, 0xb9, 0x42, 0x3e, > 0x0a, >>> 0x7e } \ >>> >>> + } >>> >>> >>> >>> #define SHELL_BCFG_HII_GUID \ >>> >>> { \ >>> >>> @@ -75,6 +79,7 @@ extern EFI_GUID gShellLevel3HiiGuid; >>> extern EFI_GUID gShellNetwork1HiiGuid; >>> >>> extern EFI_GUID gShellNetwork2HiiGuid; >>> >>> extern EFI_GUID gShellTftpHiiGuid; >>> >>> +extern EFI_GUID gShellHttpHiiGuid; >>> >>> extern EFI_GUID gShellBcfgHiiGuid; >>> >>> >>> >>> #endif >>> >>> diff --git a/ShellPkg/ShellPkg.dec b/ShellPkg/ShellPkg.dec >>> index d0843d338126..7b2d1230bd2c 100644 >>> --- a/ShellPkg/ShellPkg.dec >>> +++ b/ShellPkg/ShellPkg.dec >>> @@ -53,6 +53,7 @@ [Guids] >>> gShellNetwork1HiiGuid = {0xf3d301bb, 0xf4a5, 0x45a8, > {0xb0, 0xb7, >> 0xfa, >>> 0x99, 0x9c, 0x62, 0x37, 0xae}} >>> >>> gShellNetwork2HiiGuid = {0x174b2b5, 0xf505, 0x4b12, > {0xaa, 0x60, >> 0x59, >>> 0xdf, 0xf8, 0xd6, 0xea, 0x37}} >>> >>> gShellTftpHiiGuid = {0x738a9314, 0x82c1, 0x4592, > {0x8f, 0xf7, 0xc1, >>> 0xbd, 0xf1, 0xb2, 0x0e, 0xd4}} >>> >>> + gShellHttpHiiGuid = {0x390f84b3, 0x221c, 0x4d9e, > {0xb5, 0x06, >> 0x6d, >>> 0xb9, 0x42, 0x3e, 0x0a, 0x7e}} >>> >>> gShellBcfgHiiGuid = {0x5f5f605d, 0x1583, 0x4a2d, > {0xa6, 0xb2, 0xeb, >>> 0x12, 0xda, 0xb4, 0xa2, 0xb6}} >>> >>> gShellAcpiViewHiiGuid = {0xda8ccdf4, 0xed8f, 0x4ffc, > {0xb5, 0xef, >> 0x2e, >>> 0xf5, 0x5e, 0x24, 0x93, 0x2a}} >>> >>> # FILE_GUID as defined in ShellPkg/Application/Shell/Shell.inf >>> >>> diff --git a/ShellPkg/ShellPkg.dsc b/ShellPkg/ShellPkg.dsc >>> index 86e9f1e0040d..c42bc9464a0f 100644 >>> --- a/ShellPkg/ShellPkg.dsc >>> +++ b/ShellPkg/ShellPkg.dsc >>> @@ -139,6 +139,11 @@ [Components] >>> gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE >>> >>> } >>> >>> ShellPkg/DynamicCommand/TftpDynamicCommand/TftpApp.inf >>> >>> + >>> >> ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand >> .inf { >>> + >>> >>> + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE >>> >>> + } >>> >>> + ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf >>> >>> >> ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf >> { >>> >>> >>> gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE >>> >>> -- >>> 2.26.2.266.ge870325ee8