From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 1EF6721AE262D for ; Wed, 21 Jun 2017 00:53:08 -0700 (PDT) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 21 Jun 2017 00:54:31 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.39,368,1493708400"; d="scan'208";a="1143351778" Received: from fmsmsx107.amr.corp.intel.com ([10.18.124.205]) by orsmga001.jf.intel.com with ESMTP; 21 Jun 2017 00:52:15 -0700 Received: from fmsmsx123.amr.corp.intel.com (10.18.125.38) by fmsmsx107.amr.corp.intel.com (10.18.124.205) with Microsoft SMTP Server (TLS) id 14.3.319.2; Wed, 21 Jun 2017 00:52:15 -0700 Received: from shsmsx101.ccr.corp.intel.com (10.239.4.153) by fmsmsx123.amr.corp.intel.com (10.18.125.38) with Microsoft SMTP Server (TLS) id 14.3.319.2; Wed, 21 Jun 2017 00:52:15 -0700 Received: from shsmsx103.ccr.corp.intel.com ([169.254.4.116]) by SHSMSX101.ccr.corp.intel.com ([169.254.1.197]) with mapi id 14.03.0319.002; Wed, 21 Jun 2017 15:52:12 +0800 From: "Ye, Ting" To: "Fu, Siyuan" , "edk2-devel@lists.01.org" CC: "Wu, Jiaxin" Thread-Topic: [Patch V3] NetworkPkg/HttpBootDxe: Add HTTP Boot Callback protocol support. Thread-Index: AQHS6WPJwpJX8CwbjkWYD5ANK3hbcKIu87Hg Date: Wed, 21 Jun 2017 07:52:13 +0000 Message-ID: References: <20170620012307.9976-1-siyuan.fu@intel.com> In-Reply-To: <20170620012307.9976-1-siyuan.fu@intel.com> Accept-Language: zh-CN, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Subject: Re: [Patch V3] NetworkPkg/HttpBootDxe: Add HTTP Boot Callback protocol support. X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 21 Jun 2017 07:53:08 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Reviewed-by: Ye Ting =20 -----Original Message----- From: Fu, Siyuan=20 Sent: Tuesday, June 20, 2017 9:23 AM To: edk2-devel@lists.01.org Cc: Ye, Ting ; Wu, Jiaxin Subject: [Patch V3] NetworkPkg/HttpBootDxe: Add HTTP Boot Callback protocol= support. V3 update: Fix X64 build error. V2 update: Correct the file size print for IA32. This patch updates the HTTP Boot driver to install a default HTTP Callback = protocol if the platform doesn't provide one. This callback implementation = will print the boot file download progress in percentage format. Cc: Ye Ting Cc: Wu Jiaxin Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Fu Siyuan --- NetworkPkg/HttpBootDxe/HttpBootClient.c | 67 +++++++++- NetworkPkg/HttpBootDxe/HttpBootClient.h | 4 +- NetworkPkg/HttpBootDxe/HttpBootDhcp4.c | 26 +++- NetworkPkg/HttpBootDxe/HttpBootDhcp6.c | 106 +++++++++------ NetworkPkg/HttpBootDxe/HttpBootDxe.h | 14 ++ NetworkPkg/HttpBootDxe/HttpBootDxe.inf | 3 +- NetworkPkg/HttpBootDxe/HttpBootImpl.c | 221 +++++++++++++++++++++++++++= ++-- NetworkPkg/HttpBootDxe/HttpBootImpl.h | 2 + NetworkPkg/HttpBootDxe/HttpBootSupport.c | 29 ++++ NetworkPkg/HttpBootDx= e/HttpBootSupport.h | 34 +++++ 10 files changed, 446 insertions(+), 60 deletions(-) diff --git a/NetworkPkg/HttpBootDxe/HttpBootClient.c b/NetworkPkg/HttpBootD= xe/HttpBootClient.c index 99db3d5..68f5a49 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootClient.c +++ b/NetworkPkg/HttpBootDxe/HttpBootClient.c @@ -233,7 +233,6 @@ HttpBootDhcp4ExtractUriInfo ( // // All boot informations are valid here. // - AsciiPrint ("\n URI: %a", Private->BootFileUri); =20 // // Update the device path to include the IP and boot URI information. @@ -401,7 +400,7 @@ HttpBootDhcp6ExtractUriInfo ( // // All boot informations are valid here. // - AsciiPrint ("\n URI: %a", Private->BootFileUri); + // // Update the device path to include the IP and boot URI information. // @@ -452,6 +451,40 @@ HttpBootDiscoverBootInfo ( } =20 /** + HttpIo Callback function which will be invoked when specified HTTP_IO_CA= LLBACK_EVENT happened. + + @param[in] EventType Indicate the Event type that occurs in the = current callback. + @param[in] Message HTTP message which will be send to, or just= received from HTTP server. + @param[in] Context The Callback Context pointer. + =20 + @retval EFI_SUCCESS Tells the HttpIo to continue the HTTP proce= ss. + @retval Others Tells the HttpIo to abort the current HTTP = process. +**/ +EFI_STATUS +EFIAPI +HttpBootHttpIoCallback ( + IN HTTP_IO_CALLBACK_EVENT EventType, + IN EFI_HTTP_MESSAGE *Message, + IN VOID *Context + ) +{ + HTTP_BOOT_PRIVATE_DATA *Private; + EFI_STATUS Status; + Private =3D (HTTP_BOOT_PRIVATE_DATA *) Context; + if (Private->HttpBootCallback !=3D NULL) { + Status =3D Private->HttpBootCallback->Callback ( + Private->HttpBootCallback, + EventType =3D=3D HttpIoRequest ? HttpBootHttpRequest : Http= BootHttpResponse, + EventType =3D=3D HttpIoRequest ? FALSE : TRUE, + sizeof (EFI_HTTP_MESSAGE), + (VOID *) Message + ); + return Status; + } + return EFI_SUCCESS; +} + +/** Create a HttpIo instance for the file download. =20 @param[in] Private The pointer to the driver's private data. @@ -490,6 +523,8 @@ HttpBootCreateHttpIo ( Private->Controller, Private->UsingIpv6 ? IP_VERSION_6 : IP_VERSION_4, &ConfigData, + HttpBootHttpIoCallback, + (VOID *) Private, &Private->HttpIo ); if (EFI_ERROR (Status)) { @@ -686,6 +721,8 @@ HttpBootGetBootFileCallback ( { HTTP_BOOT_CALLBACK_DATA *CallbackData; HTTP_BOOT_ENTITY_DATA *NewEntityData; + EFI_STATUS Status; + EFI_HTTP_BOOT_CALLBACK_PROTOCOL *HttpBootCallback; =20 // // We only care about the entity data. @@ -695,6 +732,19 @@ HttpBootGetBootFileCallback ( } =20 CallbackData =3D (HTTP_BOOT_CALLBACK_DATA *) Context; + HttpBootCallback =3D CallbackData->Private->HttpBootCallback; + if (HttpBootCallback !=3D NULL) { + Status =3D HttpBootCallback->Callback ( + HttpBootCallback, + HttpBootHttpEntityBody, + TRUE, + (UINT32)Length, + Data + ); + if (EFI_ERROR (Status)) { + return Status; + } + } // // Copy data if caller has provided a buffer. // @@ -977,6 +1027,7 @@ HttpBootGetBootFile ( Context.Buffer =3D Buffer; Context.BufferSize =3D *BufferSize; Context.Cache =3D Cache; + Context.Private =3D Private; Status =3D HttpInitMsgParser ( HeaderOnly? HttpMethodHead : HttpMethodGet, ResponseData->Response.StatusCode, @@ -1032,6 +1083,18 @@ HttpBootGetBootFile ( goto ERROR_6; } ReceivedSize +=3D ResponseBody.BodyLength; + if (Private->HttpBootCallback !=3D NULL) { + Status =3D Private->HttpBootCallback->Callback ( + Private->HttpBootCallback, + HttpBootHttpEntityBody, + TRUE, + (UINT32)ResponseBody.BodyLength, + ResponseBody.Body + ); + if (EFI_ERROR (Status)) { + goto ERROR_6; + } + } } } else { // diff --git a/NetworkPkg/HttpBootDxe/HttpBootClient.h b/NetworkPkg/HttpBootD= xe/HttpBootClient.h index 2c32341..dd58719 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootClient.h +++ b/NetworkPkg/HttpBootDxe/HttpBootClient.h @@ -1,7 +1,7 @@ /** @file Declaration of the boot file download function. =20 -Copyright (c) 2015, Intel Corporation. All rights reserved.
+Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.
(C) Copyright 2016 Hewlett Packard Enterprise Development LP
This pro= gram and the accompanying materials are licensed and made available under = the terms and conditions of the BSD License that accompanies this distribut= ion. =20 @@ -64,6 +64,8 @@ typedef struct { UINTN CopyedSize; UINTN BufferSize; UINT8 *Buffer; + + HTTP_BOOT_PRIVATE_DATA *Private; } HTTP_BOOT_CALLBACK_DATA; =20 /** diff --git a/NetworkPkg/HttpBootDxe/HttpBootDhcp4.c b/NetworkPkg/HttpBootDx= e/HttpBootDhcp4.c index fcea916..a8cee04 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootDhcp4.c +++ b/NetworkPkg/HttpBootDxe/HttpBootDhcp4.c @@ -1,7 +1,7 @@ /** @file Functions implementation related with DHCPv4 for HTTP boot driver. =20 -Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made availabl= e under the terms and conditions of the BSD License that accompanies this = distribution. =20 The full text of the license may be found at @@ -609,8 +609,13 @@ HttpBoot= Dhcp4CallBack ( EFI_DHCP4_PACKET_OPTION *MaxMsgSize; UINT16 Value; EFI_STATUS Status; + BOOLEAN Received; =20 - if ((Dhcp4Event !=3D Dhcp4RcvdOffer) && (Dhcp4Event !=3D Dhcp4SelectOffe= r)) { + if ((Dhcp4Event !=3D Dhcp4SendDiscover) &&=20 + (Dhcp4Event !=3D Dhcp4RcvdOffer) &&=20 + (Dhcp4Event !=3D Dhcp4SendRequest) &&=20 + (Dhcp4Event !=3D Dhcp4RcvdAck) &&=20 + (Dhcp4Event !=3D Dhcp4SelectOffer)) { return EFI_SUCCESS; } =20 @@ -628,6 +633,23 @@ HttpBootDhcp4CallBack ( Value =3D HTONS (HTTP_BOOT_DHCP4_PACKET_MAX_SIZE); CopyMem (MaxMsgSize->Data, &Value, sizeof (Value)); } + =20 + // + // Callback to user if any packets sent or received. + // + if (Private->HttpBootCallback !=3D NULL && Dhcp4Event !=3D Dhcp4SelectOf= fer) { + Received =3D (BOOLEAN) (Dhcp4Event =3D=3D Dhcp4RcvdOffer || Dhcp4Event= =3D=3D Dhcp4RcvdAck); + Status =3D Private->HttpBootCallback->Callback ( + Private->HttpBootCallback,=20 + HttpBootDhcp4, + Received, + Packet->Length, + &Packet->Dhcp4 + ); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + } =20 Status =3D EFI_SUCCESS; switch (Dhcp4Event) { diff --git a/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c b/NetworkPkg/HttpBootDx= e/HttpBootDhcp6.c index f2b8195..4eea895 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c +++ b/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c @@ -1,7 +1,7 @@ /** @file Functions implementation related with DHCPv6 for HTTP boot driver. =20 -Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made availabl= e under the terms and conditions of the BSD License that accompanies this = distribution. =20 The full text of the license may be found at @@ -431,56 +431,78 @@ HttpBoo= tDhcp6CallBack ( OUT EFI_DHCP6_PACKET **NewPacket OPTIONAL ) { - HTTP_BOOT_PRIVATE_DATA *Private; - EFI_DHCP6_PACKET *SelectAd; - EFI_STATUS Status; + HTTP_BOOT_PRIVATE_DATA *Private; + EFI_DHCP6_PACKET *SelectAd; + EFI_STATUS Status; + BOOLEAN Received; + =20 + if ((Dhcp6Event !=3D Dhcp6SendSolicit) && + (Dhcp6Event !=3D Dhcp6RcvdAdvertise) && + (Dhcp6Event !=3D Dhcp6SendRequest) && + (Dhcp6Event !=3D Dhcp6RcvdReply) && + (Dhcp6Event !=3D Dhcp6SelectAdvertise)) { + return EFI_SUCCESS; + } =20 - ASSERT (Packet !=3D NULL); + ASSERT (Packet !=3D NULL); + =20 + Private =3D (HTTP_BOOT_PRIVATE_DATA *) Context; + Status =3D EFI_SUCCESS; + if (Private->HttpBootCallback !=3D NULL && Dhcp6Event !=3D Dhcp6SelectAd= vertise) { + Received =3D (BOOLEAN) (Dhcp6Event =3D=3D Dhcp6RcvdAdvertise || Dhcp6E= vent =3D=3D Dhcp6RcvdReply); + Status =3D Private->HttpBootCallback->Callback ( + Private->HttpBootCallback,=20 + HttpBootDhcp6, + Received, + Packet->Length, + &Packet->Dhcp6 + ); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + } + switch (Dhcp6Event) { =20 - Private =3D (HTTP_BOOT_PRIVATE_DATA *) Context; - Status =3D EFI_SUCCESS; - switch (Dhcp6Event) { - =20 - case Dhcp6RcvdAdvertise: - Status =3D EFI_NOT_READY; + case Dhcp6RcvdAdvertise: + Status =3D EFI_NOT_READY; if (Packet->Length > HTTP_BOOT_DHCP6_PACKET_MAX_SIZE) { // // Ignore the incoming packets which exceed the maximum length. // break; } - if (Private->OfferNum < HTTP_BOOT_OFFER_MAX_NUM) { - // - // Cache the dhcp offers to OfferBuffer[] for select later, and rec= ord - // the OfferIndex and OfferCount. - // If error happens, just ignore this packet and continue to wait m= ore offer. - // - HttpBootCacheDhcp6Offer (Private, Packet); - } - break; - - case Dhcp6SelectAdvertise: - // - // Select offer by the default policy or by order, and record the Sel= ectIndex - // and SelectProxyType. - // - HttpBootSelectDhcpOffer (Private); - - if (Private->SelectIndex =3D=3D 0) { - Status =3D EFI_ABORTED; - } else { - ASSERT (NewPacket !=3D NULL); - SelectAd =3D &Private->OfferBuffer[Private->SelectIndex - 1].Dhcp= 6.Packet.Offer; - *NewPacket =3D AllocateZeroPool (SelectAd->Size); - if (*NewPacket =3D=3D NULL) { - return EFI_OUT_OF_RESOURCES; - } - CopyMem (*NewPacket, SelectAd, SelectAd->Size); - } - break; + if (Private->OfferNum < HTTP_BOOT_OFFER_MAX_NUM) { + // + // Cache the dhcp offers to OfferBuffer[] for select later, and reco= rd + // the OfferIndex and OfferCount. + // If error happens, just ignore this packet and continue to wait mo= re offer. + // + HttpBootCacheDhcp6Offer (Private, Packet); + } + break; + + case Dhcp6SelectAdvertise: + // + // Select offer by the default policy or by order, and record the Sele= ctIndex + // and SelectProxyType. + // + HttpBootSelectDhcpOffer (Private); + + if (Private->SelectIndex =3D=3D 0) { + Status =3D EFI_ABORTED; + } else { + ASSERT (NewPacket !=3D NULL); + SelectAd =3D &Private->OfferBuffer[Private->SelectIndex - 1].Dhcp6= .Packet.Offer; + *NewPacket =3D AllocateZeroPool (SelectAd->Size); + if (*NewPacket =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem (*NewPacket, SelectAd, SelectAd->Size); + } + break; =20 - default: - break; + default: + break; } =20 return Status; =20 diff --git a/NetworkPkg/HttpBootDxe/HttpBootDxe.h b/NetworkPkg/HttpBootDxe/= HttpBootDxe.h index a1e6792..8d89b3e 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootDxe.h +++ b/NetworkPkg/HttpBootDxe/HttpBootDxe.h @@ -62,6 +62,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER= EXPRESS OR IMPLIED. // Produced Protocols // #include +#include =20 // // Consumed Guids @@ -133,6 +134,14 @@ struct _HTTP_BOOT_VIRTUAL_NIC { CallbackInfo, \ HTTP_BOOT_PRIVATE_DATA_SIGNATURE \ ) + =20 +#define HTTP_BOOT_PRIVATE_DATA_FROM_CALLBACK_PROTOCOL(CallbackProtocol) \ + CR ( \ + CallbackProtocol, \ + HTTP_BOOT_PRIVATE_DATA, \ + LoadFileCallback, \ + HTTP_BOOT_PRIVATE_DATA_SIGNATURE \ + ) =20 struct _HTTP_BOOT_PRIVATE_DATA { UINT32 Signature; @@ -168,6 +177,11 @@ struct _HTTP_BOOT_PRIVATE_DATA { EFI_LOAD_FILE_PROTOCOL LoadFile; EFI_DEVICE_PATH_PROTOCOL *DevicePath; UINT32 Id; + EFI_HTTP_BOOT_CALLBACK_PROTOCOL *HttpBootCallback; + EFI_HTTP_BOOT_CALLBACK_PROTOCOL LoadFileCallback; + UINT64 FileSize; + UINT64 ReceivedSize; + UINT32 Percentage; =20 // // HII callback info block diff --git a/NetworkPkg/HttpBootDxe/HttpBootDxe.inf b/NetworkPkg/HttpBootDx= e/HttpBootDxe.inf index ec983ba..4d6c5e5 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootDxe.inf +++ b/NetworkPkg/HttpBootDxe/HttpBootDxe.inf @@ -85,7 +85,8 @@ gEfiNetworkInterfaceIdentifierProtocolGuid_31 ## SOMETIMES_CONSUMES gEfiRamDiskProtocolGuid ## SOMETIMES_CONSUMES gEfiHiiConfigAccessProtocolGuid ## BY_START - + gEfiHttpBootCallbackProtocolGuid ## SOMETIMES_PRODUCES + =20 [Guids] ## SOMETIMES_CONSUMES ## GUID # HiiIsConfigHdrMatch mHttpBootConfigSto= rageName ## SOMETIMES_PRODUCES ## GUID # HiiConstructConfigHdr mHttpBootConfigSto= rageName diff --git a/NetworkPkg/HttpBootDxe/HttpBootImpl.c b/NetworkPkg/Ht= tpBootDxe/HttpBootImpl.c index cf6de80..56f5bab 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootImpl.c +++ b/NetworkPkg/HttpBootDxe/HttpBootImpl.c @@ -16,6 +16,84 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHE= R EXPRESS OR IMPLIED. #include "HttpBootDxe.h" =20 /** + Install HTTP Boot Callback Protocol if not installed before. + + @param[in] Private Pointer to HTTP Boot private data. + + @retval EFI_SUCCESS HTTP Boot Callback Protocol installed succe= sfully. + @retval Others Failed to install HTTP Boot Callback Protoc= ol. + +**/ +EFI_STATUS +HttpBootInstallCallback ( + IN HTTP_BOOT_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + EFI_HANDLE ControllerHandle; + + if (!Private->UsingIpv6) { + ControllerHandle =3D Private->Ip4Nic->Controller; } else { + ControllerHandle =3D Private->Ip6Nic->Controller; } + + // + // Check whether gEfiHttpBootCallbackProtocolGuid already installed. + // + Status =3D gBS->HandleProtocol ( + ControllerHandle, + &gEfiHttpBootCallbackProtocolGuid, + (VOID **) &Private->HttpBootCallback + ); + if (Status =3D=3D EFI_UNSUPPORTED) { + + CopyMem ( + &Private->LoadFileCallback, + &gHttpBootDxeHttpBootCallback, + sizeof (EFI_HTTP_BOOT_CALLBACK_PROTOCOL) + ); + + // + // Install a default callback if user didn't offer one. + // + Status =3D gBS->InstallProtocolInterface ( + &ControllerHandle, + &gEfiHttpBootCallbackProtocolGuid, + EFI_NATIVE_INTERFACE, + &Private->LoadFileCallback + ); + if (EFI_ERROR (Status)) { + return Status; + } + Private->HttpBootCallback =3D &Private->LoadFileCallback; } + + return EFI_SUCCESS; +} + +/** + Uninstall HTTP Boot Callback Protocol if it's installed by this driver. + + @param[in] Private Pointer to HTTP Boot private data. + +**/ +VOID +HttpBootUninstallCallback ( + IN HTTP_BOOT_PRIVATE_DATA *Private + ) +{ + if (Private->HttpBootCallback =3D=3D &Private->LoadFileCallback) { + gBS->UninstallProtocolInterface ( + Private->Controller, + &gEfiHttpBootCallbackProtocolGuid, + &Private->HttpBootCallback + ); + Private->HttpBootCallback =3D NULL; + } +} + +/** Enable the use of UEFI HTTP boot function. =20 If the driver has already been started but not satisfy the requirement (= IP stack and @@ -144,6 +222,7 @@ HttpBootStart ( } } Private->Started =3D TRUE; + Print (L"\n>>Start HTTP Boot over IPv%d", Private->UsingIpv6 ? 6 :=20 + 4); =20 return EFI_SUCCESS; } @@ -237,7 +316,10 @@ HttpBootLoadFile ( return EFI_NOT_STARTED; } =20 - Status =3D EFI_DEVICE_ERROR; + Status =3D HttpBootInstallCallback (Private); if (EFI_ERROR(Status)) { + goto ON_EXIT; + } =20 if (Private->BootFileUri =3D=3D NULL) { // @@ -245,7 +327,7 @@ HttpBootLoadFile ( // Status =3D HttpBootDiscoverBootInfo (Private); if (EFI_ERROR (Status)) { - return Status; + goto ON_EXIT; } } =20 @@ -255,7 +337,7 @@ HttpBootLoadFile ( // Status =3D HttpBootCreateHttpIo (Private); if (EFI_ERROR (Status)) { - return Status; + goto ON_EXIT; } } =20 @@ -287,7 +369,7 @@ HttpBootLoadFile ( &Private->ImageType ); if (EFI_ERROR (Status) && Status !=3D EFI_BUFFER_TOO_SMALL) { - return Status; + goto ON_EXIT; } } } @@ -295,19 +377,24 @@ HttpBootLoadFile ( if (*BufferSize < Private->BootFileSize) { *BufferSize =3D Private->BootFileSize; *ImageType =3D Private->ImageType; - return EFI_BUFFER_TOO_SMALL; + Status =3D EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; } =20 // // Load the boot file into Buffer // - return HttpBootGetBootFile ( - Private, - FALSE, - BufferSize, - Buffer, - ImageType - ); + Status =3D HttpBootGetBootFile ( + Private, + FALSE, + BufferSize, + Buffer, + ImageType + ); + =20 +ON_EXIT: + HttpBootUninstallCallback (Private); + return Status; } =20 /** @@ -520,3 +607,113 @@ GLOBAL_REMOVE_IF_UNREFERENCED EFI_LOAD_FILE_PROTOCOL= gHttpBootDxeLoadFile =3D { HttpBootDxeLoadFile }; + +/** + Callback function that is invoked when the HTTP Boot driver is about=20 +to transmit or has received a + packet. + + This function is invoked when the HTTP Boot driver is about to transmit = or has received packet. + Parameters DataType and Received specify the type of event and the=20 + format of the buffer pointed to by Data. Due to the polling nature of=20 + UEFI device drivers, this callback function should not execute for more = than 5 ms. + The returned status code determines the behavior of the HTTP Boot driver= . + + @param[in] This Pointer to the EFI_HTTP_BOOT_CALLBACK_PR= OTOCOL instance. + @param[in] DataType The event that occurs in the current sta= te. + @param[in] Received TRUE if the callback is being invoked du= e to a receive event. + FALSE if the callback is being invoked d= ue to a transmit event. + @param[in] DataLength The length in bytes of the buffer pointe= d to by Data. + @param[in] Data A pointer to the buffer of data, the dat= a type is specified by + DataType. + =20 + @retval EFI_SUCCESS Tells the HTTP Boot driver to continue t= he HTTP Boot process. + @retval EFI_ABORTED Tells the HTTP Boot driver to abort the = current HTTP Boot process. +**/ +EFI_STATUS +HttpBootCallback ( + IN EFI_HTTP_BOOT_CALLBACK_PROTOCOL *This, + IN EFI_HTTP_BOOT_CALLBACK_DATA_TYPE DataType, + IN BOOLEAN Received, + IN UINT32 DataLength, + IN VOID *Data OPTIONAL + ) +{ + EFI_HTTP_MESSAGE *HttpMessage; + EFI_HTTP_HEADER *HttpHeader; + HTTP_BOOT_PRIVATE_DATA *Private; + UINT32 Percentage; + + Private =3D HTTP_BOOT_PRIVATE_DATA_FROM_CALLBACK_PROTOCOL(This); + + switch (DataType) { + case HttpBootDhcp4: + case HttpBootDhcp6: + Print (L"."); + break; + + case HttpBootHttpRequest: + if (Data !=3D NULL) { + HttpMessage =3D (EFI_HTTP_MESSAGE *) Data; + if (HttpMessage->Data.Request->Method =3D=3D HttpMethodGet && + HttpMessage->Data.Request->Url !=3D NULL) { + Print (L"\n URI: %s\n", HttpMessage->Data.Request->Url); + } + } + break; + + case HttpBootHttpResponse: + if (Data !=3D NULL) { + HttpMessage =3D (EFI_HTTP_MESSAGE *) Data; + HttpHeader =3D HttpFindHeader ( + HttpMessage->HeaderCount, + HttpMessage->Headers, + HTTP_HEADER_CONTENT_LENGTH + ); + if (HttpHeader !=3D NULL) { + Private->FileSize =3D AsciiStrDecimalToUintn (HttpHeader->FieldVal= ue); + Private->ReceivedSize =3D 0; + Private->Percentage =3D 0; + } + } + break; + + case HttpBootHttpEntityBody: + if (DataLength !=3D 0) { + if (Private->FileSize !=3D 0) { + // + // We already know the file size, print in percentage format. + // + if (Private->ReceivedSize =3D=3D 0) { + Print (L" File Size: %lu\n", Private->FileSize); + } + Private->ReceivedSize +=3D DataLength; + Percentage =3D (UINT32) DivU64x64Remainder (MultU64x32 (Private->R= eceivedSize, 100), Private->FileSize, NULL); + if (Private->Percentage !=3D Percentage) { + Private->Percentage =3D Percentage; + Print (L"\r Downloading...%d%%", Percentage); + } + } else { + // + // In some case we couldn't get the file size from the HTTP header= , so we + // just print the downloaded file size. + // + Private->ReceivedSize +=3D DataLength; + Print (L"\r Downloading...%lu Bytes", Private->ReceivedSize); + } + } + break; + + default: + break; + }; + + return EFI_SUCCESS; +} + +/// +/// HTTP Boot Callback Protocol instance ///=20 +GLOBAL_REMOVE_IF_UNREFERENCED EFI_HTTP_BOOT_CALLBACK_PROTOCOL =20 +gHttpBootDxeHttpBootCallback =3D { + HttpBootCallback +}; diff --git a/NetworkPkg/HttpBootDxe/HttpBootImpl.h b/NetworkPkg/HttpBootDxe= /HttpBootImpl.h index 7066338..da58bb6 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootImpl.h +++ b/NetworkPkg/HttpBootDxe/HttpBootImpl.h @@ -47,4 +47,6 @@ HttpBootStop ( IN HTTP_BOOT_PRIVATE_DATA *Private ); =20 +extern EFI_HTTP_BOOT_CALLBACK_PROTOCOL gHttpBootDxeHttpBootCallback; + #endif diff --git a/NetworkPkg/HttpBootDxe/HttpBootSupport.c b/NetworkPkg/HttpBoot= Dxe/HttpBootSupport.c index 8fe81eb..5024f2e 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootSupport.c +++ b/NetworkPkg/HttpBootDxe/HttpBootSupport.c @@ -671,6 +671,9 @@ HttpIoNotify ( @param[in] Controller The handle of the controller. @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6. @param[in] ConfigData The HTTP_IO configuration data. + @param[in] Callback Callback function which will be invoked when = specified + HTTP_IO_CALLBACK_EVENT happened. + @param[in] Context The Context data which will be passed to the = Callback function. @param[out] HttpIo The HTTP_IO. =20 @retval EFI_SUCCESS The HTTP_IO is created and configured. @@ -687,6 +690,8 @@ HttpIoCreateIo ( IN EFI_HANDLE Controller, IN UINT8 IpVersion, IN HTTP_IO_CONFIG_DATA *ConfigData, + IN HTTP_IO_CALLBACK Callback, + IN VOID *Context, OUT HTTP_IO *HttpIo ) { @@ -739,6 +744,8 @@ HttpIoCreateIo ( HttpIo->Controller =3D Controller; HttpIo->IpVersion =3D IpVersion; HttpIo->Http =3D Http; + HttpIo->Callback =3D Callback; + HttpIo->Context =3D Context; =20 ZeroMem (&HttpConfigData, sizeof (EFI_HTTP_CONFIG_DATA)); HttpConfigData.HttpVersion =3D HttpVersion11; @@ -908,6 +915,17 @@ HttpIoSendRequest ( HttpIo->ReqToken.Message->BodyLength =3D BodyLength; HttpIo->ReqToken.Message->Body =3D Body; =20 + if (HttpIo->Callback !=3D NULL) { + Status =3D HttpIo->Callback ( + HttpIoRequest, + HttpIo->ReqToken.Message, + HttpIo->Context + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + // // Queue the request token to HTTP instances. // @@ -1016,6 +1034,17 @@ HttpIoRecvResponse ( HttpIo->IsRxDone =3D FALSE; } =20 + if (!EFI_ERROR (HttpIo->RspToken.Status) && HttpIo->Callback !=3D NULL) = { + Status =3D HttpIo->Callback ( + HttpIoResponse, + HttpIo->RspToken.Message, + HttpIo->Context + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + // // Store the received data into the wrapper. // diff --git a/NetworkPkg/HttpBootDxe/HttpBootSupport.h b/NetworkPkg/HttpBoot= Dxe/HttpBootSupport.h index 65302d2..f2b1846 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootSupport.h +++ b/NetworkPkg/HttpBootDxe/HttpBootSupport.h @@ -145,6 +145,32 @@ HttpBootSetHeader ( IN CHAR8 *FieldValue ); =20 +/// +/// HTTP_IO_CALLBACK_EVENT +/// +typedef enum { + HttpIoRequest, + HttpIoResponse +} HTTP_IO_CALLBACK_EVENT; + +/** + HttpIo Callback function which will be invoked when specified HTTP_IO_CA= LLBACK_EVENT happened. + + @param[in] EventType Indicate the Event type that occurs in the = current callback. + @param[in] Message HTTP message which will be send to, or just= received from HTTP server. + @param[in] Context The Callback Context pointer. + =20 + @retval EFI_SUCCESS Tells the HttpIo to continue the HTTP proce= ss. + @retval Others Tells the HttpIo to abort the current HTTP = process. +**/ +typedef +EFI_STATUS +(EFIAPI * HTTP_IO_CALLBACK) ( + IN HTTP_IO_CALLBACK_EVENT EventType, + IN EFI_HTTP_MESSAGE *Message, + IN VOID *Context + ); + // // HTTP_IO configuration data for IPv4 // @@ -189,6 +215,9 @@ typedef struct { =20 EFI_HTTP_PROTOCOL *Http; =20 + HTTP_IO_CALLBACK Callback; + VOID *Context; + EFI_HTTP_TOKEN ReqToken; EFI_HTTP_MESSAGE ReqMessage; EFI_HTTP_TOKEN RspToken; @@ -252,6 +281,9 @@ HttpBootCommonNotify ( @param[in] Controller The handle of the controller. @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6. @param[in] ConfigData The HTTP_IO configuration data. + @param[in] Callback Callback function which will be invoked when = specified + HTTP_IO_CALLBACK_EVENT happened. + @param[in] Context The Context data which will be passed to the = Callback function. @param[out] HttpIo The HTTP_IO. =20 @retval EFI_SUCCESS The HTTP_IO is created and configured. @@ -268,6 +300,8 @@ HttpIoCreateIo ( IN EFI_HANDLE Controller, IN UINT8 IpVersion, IN HTTP_IO_CONFIG_DATA *ConfigData, + IN HTTP_IO_CALLBACK Callback, + IN VOID *Context, OUT HTTP_IO *HttpIo ); =20 -- 1.9.5.msysgit.1