From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) (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 7339A21A07A8C for ; Mon, 19 Jun 2017 18:28:26 -0700 (PDT) Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 19 Jun 2017 18:29:46 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.39,363,1493708400"; d="scan'208";a="869717685" Received: from fmsmsx103.amr.corp.intel.com ([10.18.124.201]) by FMSMGA003.fm.intel.com with ESMTP; 19 Jun 2017 18:29:45 -0700 Received: from fmsmsx152.amr.corp.intel.com (10.18.125.5) by FMSMSX103.amr.corp.intel.com (10.18.124.201) with Microsoft SMTP Server (TLS) id 14.3.319.2; Mon, 19 Jun 2017 18:29:45 -0700 Received: from shsmsx101.ccr.corp.intel.com (10.239.4.153) by FMSMSX152.amr.corp.intel.com (10.18.125.5) with Microsoft SMTP Server (TLS) id 14.3.319.2; Mon, 19 Jun 2017 18:29:45 -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; Tue, 20 Jun 2017 09:29:43 +0800 From: "Wu, Jiaxin" To: "Fu, Siyuan" , "edk2-devel@lists.01.org" CC: "Ye, Ting" Thread-Topic: [Patch V3] NetworkPkg/HttpBootDxe: Add HTTP Boot Callback protocol support. Thread-Index: AQHS6WPJuSCTJH4yYU+WquRGV79t16Is9oZw Date: Tue, 20 Jun 2017 01:29:42 +0000 Message-ID: <895558F6EA4E3B41AC93A00D163B7274162DCF6D@SHSMSX103.ccr.corp.intel.com> References: <20170620012307.9976-1-siyuan.fu@intel.com> In-Reply-To: <20170620012307.9976-1-siyuan.fu@intel.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiYTVmOTMwNjQtOTI4MS00MGMzLTgwNDAtMWVlNDcxODk2ODYyIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX0lDIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE2LjUuOS4zIiwiVHJ1c3RlZExhYmVsSGFzaCI6Im9KS2dcL3p2ck9ab2Vjc1FlUlV0azZiNVVITGVha0ZXVXRHWVVHanNiVG5vPSJ9 x-ctpclassification: CTP_IC dlp-product: dlpe-windows dlp-version: 10.0.102.7 dlp-reaction: no-action 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: Tue, 20 Jun 2017 01:28:26 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Reviewed-by: Wu Jiaxin > -----Original Message----- > From: Fu, Siyuan > 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. >=20 > V3 update: > Fix X64 build error. >=20 > V2 update: > Correct the file size print for IA32. >=20 > This patch updates the HTTP Boot driver to install a default HTTP Callbac= k > protocol > if the platform doesn't provide one. This callback implementation will pr= int > the > boot file download progress in percentage format. >=20 > 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/HttpBootDxe/HttpBootSupport.h | 34 +++++ > 10 files changed, 446 insertions(+), 60 deletions(-) >=20 > diff --git a/NetworkPkg/HttpBootDxe/HttpBootClient.c > b/NetworkPkg/HttpBootDxe/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_CALLBACK_EVENT happened. > + > + @param[in] EventType Indicate the Event type that occurs in th= e > current callback. > + @param[in] Message HTTP message which will be send to, or ju= st > received from HTTP server. > + @param[in] Context The Callback Context pointer. > + > + @retval EFI_SUCCESS Tells the HttpIo to continue the HTTP pro= cess. > + @retval Others Tells the HttpIo to abort the current HTT= P 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 : > HttpBootHttpResponse, > + 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/HttpBootDxe/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 program and the accompanying materials are licensed and made > available under > the terms and conditions of the BSD License that accompanies this > distribution. > @@ -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/HttpBootDxe/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 > available under > the terms and conditions of the BSD License that accompanies this > distribution. > The full text of the license may be found at > @@ -609,8 +609,13 @@ HttpBootDhcp4CallBack ( > EFI_DHCP4_PACKET_OPTION *MaxMsgSize; > UINT16 Value; > EFI_STATUS Status; > + BOOLEAN Received; >=20 > - if ((Dhcp4Event !=3D Dhcp4RcvdOffer) && (Dhcp4Event !=3D Dhcp4SelectOf= fer)) > { > + if ((Dhcp4Event !=3D Dhcp4SendDiscover) && > + (Dhcp4Event !=3D Dhcp4RcvdOffer) && > + (Dhcp4Event !=3D Dhcp4SendRequest) && > + (Dhcp4Event !=3D Dhcp4RcvdAck) && > + (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)); > } > + > + // > + // Callback to user if any packets sent or received. > + // > + if (Private->HttpBootCallback !=3D NULL && Dhcp4Event !=3D Dhcp4Select= Offer) > { > + Received =3D (BOOLEAN) (Dhcp4Event =3D=3D Dhcp4RcvdOffer || Dhcp4Eve= nt > =3D=3D Dhcp4RcvdAck); > + Status =3D Private->HttpBootCallback->Callback ( > + Private->HttpBootCallback, > + 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/HttpBootDxe/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 > available under > the terms and conditions of the BSD License that accompanies this > distribution. > The full text of the license may be found at > @@ -431,56 +431,78 @@ HttpBootDhcp6CallBack ( > 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; > + > + 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); > + > + Private =3D (HTTP_BOOT_PRIVATE_DATA *) Context; > + Status =3D EFI_SUCCESS; > + if (Private->HttpBootCallback !=3D NULL && Dhcp6Event !=3D > Dhcp6SelectAdvertise) { > + Received =3D (BOOLEAN) (Dhcp6Event =3D=3D Dhcp6RcvdAdvertise || > Dhcp6Event =3D=3D Dhcp6RcvdReply); > + Status =3D Private->HttpBootCallback->Callback ( > + Private->HttpBootCallback, > + 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) { > - > - 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 r= ecord > - // the OfferIndex and OfferCount. > - // If error happens, just ignore this packet and continue to wait= more > offer. > - // > - HttpBootCacheDhcp6Offer (Private, Packet); > - } > - break; > - > - case Dhcp6SelectAdvertise: > - // > - // Select offer by the default policy or by order, and record the > SelectIndex > - // 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; > + if (Private->OfferNum < HTTP_BOOT_OFFER_MAX_NUM) { > + // > + // Cache the dhcp offers to OfferBuffer[] for select later, and re= cord > + // the OfferIndex and OfferCount. > + // If error happens, just ignore this packet and continue to wait = more > offer. > + // > + HttpBootCacheDhcp6Offer (Private, Packet); > + } > + break; > + > + case Dhcp6SelectAdvertise: > + // > + // Select offer by the default policy or by order, and record the > SelectIndex > + // 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; > 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 \ > ) > + > +#define > HTTP_BOOT_PRIVATE_DATA_FROM_CALLBACK_PROTOCOL(CallbackProtoco > l) \ > + 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/HttpBootDxe/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 > + > [Guids] > ## SOMETIMES_CONSUMES ## GUID # HiiIsConfigHdrMatch > mHttpBootConfigStorageName > ## SOMETIMES_PRODUCES ## GUID # HiiConstructConfigHdr > mHttpBootConfigStorageName > diff --git a/NetworkPkg/HttpBootDxe/HttpBootImpl.c > b/NetworkPkg/HttpBootDxe/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, EITHER 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 suc= cesfully. > + @retval Others Failed to install HTTP Boot Callback Prot= ocol. > + > +**/ > +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 : 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 > + ); > + > +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 t= o > transmit or has received a > + packet. > + > + This function is invoked when the HTTP Boot driver is about to transmi= t or > has received packet. > + Parameters DataType and Received specify the type of event and the > format of the buffer pointed > + to by Data. Due to the polling nature of UEFI device drivers, this cal= lback > function should not > + execute for more than 5 ms. > + The returned status code determines the behavior of the HTTP Boot driv= er. > + > + @param[in] This Pointer to the > EFI_HTTP_BOOT_CALLBACK_PROTOCOL instance. > + @param[in] DataType The event that occurs in the current s= tate. > + @param[in] Received TRUE if the callback is being invoked = due to a > receive event. > + FALSE if the callback is being invoked= due to a transmit > event. > + @param[in] DataLength The length in bytes of the buffer poin= ted to > by Data. > + @param[in] Data A pointer to the buffer of data, the d= ata type is > specified by > + DataType. > + > + @retval EFI_SUCCESS Tells the HTTP Boot driver to continue= the > HTTP Boot process. > + @retval EFI_ABORTED Tells the HTTP Boot driver to abort th= e 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->FieldV= alue); > + 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- > >ReceivedSize, 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 head= er, 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 > +/// > +GLOBAL_REMOVE_IF_UNREFERENCED > +EFI_HTTP_BOOT_CALLBACK_PROTOCOL 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/HttpBootDxe/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 whe= n > specified > + HTTP_IO_CALLBACK_EVENT happened. > + @param[in] Context The Context data which will be passed to th= e > 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/HttpBootDxe/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_CALLBACK_EVENT happened. > + > + @param[in] EventType Indicate the Event type that occurs in th= e > current callback. > + @param[in] Message HTTP message which will be send to, or ju= st > received from HTTP server. > + @param[in] Context The Callback Context pointer. > + > + @retval EFI_SUCCESS Tells the HttpIo to continue the HTTP pro= cess. > + @retval Others Tells the HttpIo to abort the current HTT= P 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 whe= n > specified > + HTTP_IO_CALLBACK_EVENT happened. > + @param[in] Context The Context data which will be passed to th= e > 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