Reviewed-by: Wu Jiaxin <jiaxin...@intel.com>
> -----Original Message----- > From: Fu, Siyuan > Sent: Tuesday, June 20, 2017 9:23 AM > To: edk2-devel@lists.01.org > Cc: Ye, Ting <ting...@intel.com>; Wu, Jiaxin <jiaxin...@intel.com> > 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 <ting...@intel.com> > Cc: Wu Jiaxin <jiaxin...@intel.com> > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Fu Siyuan <siyuan...@intel.com> > --- > 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(-) > > 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); > > // > // 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 ( > } > > /** > + HttpIo Callback function which will be invoked when specified > HTTP_IO_CALLBACK_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. > + > + @retval EFI_SUCCESS Tells the HttpIo to continue the HTTP process. > + @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 = (HTTP_BOOT_PRIVATE_DATA *) Context; > + if (Private->HttpBootCallback != NULL) { > + Status = Private->HttpBootCallback->Callback ( > + Private->HttpBootCallback, > + EventType == HttpIoRequest ? HttpBootHttpRequest : > HttpBootHttpResponse, > + EventType == HttpIoRequest ? FALSE : TRUE, > + sizeof (EFI_HTTP_MESSAGE), > + (VOID *) Message > + ); > + return Status; > + } > + return EFI_SUCCESS; > +} > + > +/** > Create a HttpIo instance for the file download. > > @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; > > // > // We only care about the entity data. > @@ -695,6 +732,19 @@ HttpBootGetBootFileCallback ( > } > > CallbackData = (HTTP_BOOT_CALLBACK_DATA *) Context; > + HttpBootCallback = CallbackData->Private->HttpBootCallback; > + if (HttpBootCallback != NULL) { > + Status = 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 = Buffer; > Context.BufferSize = *BufferSize; > Context.Cache = Cache; > + Context.Private = Private; > Status = HttpInitMsgParser ( > HeaderOnly? HttpMethodHead : HttpMethodGet, > ResponseData->Response.StatusCode, > @@ -1032,6 +1083,18 @@ HttpBootGetBootFile ( > goto ERROR_6; > } > ReceivedSize += ResponseBody.BodyLength; > + if (Private->HttpBootCallback != NULL) { > + Status = 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. > > -Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> > +Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR> > (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR> > 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; > > /** > 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. > > -Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR> > +Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR> > 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; > > - if ((Dhcp4Event != Dhcp4RcvdOffer) && (Dhcp4Event != Dhcp4SelectOffer)) > { > + if ((Dhcp4Event != Dhcp4SendDiscover) && > + (Dhcp4Event != Dhcp4RcvdOffer) && > + (Dhcp4Event != Dhcp4SendRequest) && > + (Dhcp4Event != Dhcp4RcvdAck) && > + (Dhcp4Event != Dhcp4SelectOffer)) { > return EFI_SUCCESS; > } > > @@ -628,6 +633,23 @@ HttpBootDhcp4CallBack ( > Value = 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 != NULL && Dhcp4Event != Dhcp4SelectOffer) > { > + Received = (BOOLEAN) (Dhcp4Event == Dhcp4RcvdOffer || Dhcp4Event > == Dhcp4RcvdAck); > + Status = Private->HttpBootCallback->Callback ( > + Private->HttpBootCallback, > + HttpBootDhcp4, > + Received, > + Packet->Length, > + &Packet->Dhcp4 > + ); > + if (EFI_ERROR (Status)) { > + return EFI_ABORTED; > + } > + } > > Status = 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. > > -Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR> > +Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR> > 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 != Dhcp6SendSolicit) && > + (Dhcp6Event != Dhcp6RcvdAdvertise) && > + (Dhcp6Event != Dhcp6SendRequest) && > + (Dhcp6Event != Dhcp6RcvdReply) && > + (Dhcp6Event != Dhcp6SelectAdvertise)) { > + return EFI_SUCCESS; > + } > > - ASSERT (Packet != NULL); > + ASSERT (Packet != NULL); > + > + Private = (HTTP_BOOT_PRIVATE_DATA *) Context; > + Status = EFI_SUCCESS; > + if (Private->HttpBootCallback != NULL && Dhcp6Event != > Dhcp6SelectAdvertise) { > + Received = (BOOLEAN) (Dhcp6Event == Dhcp6RcvdAdvertise || > Dhcp6Event == Dhcp6RcvdReply); > + Status = Private->HttpBootCallback->Callback ( > + Private->HttpBootCallback, > + HttpBootDhcp6, > + Received, > + Packet->Length, > + &Packet->Dhcp6 > + ); > + if (EFI_ERROR (Status)) { > + return EFI_ABORTED; > + } > + } > + switch (Dhcp6Event) { > > - Private = (HTTP_BOOT_PRIVATE_DATA *) Context; > - Status = EFI_SUCCESS; > - switch (Dhcp6Event) { > - > - case Dhcp6RcvdAdvertise: > - Status = EFI_NOT_READY; > + case Dhcp6RcvdAdvertise: > + Status = 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 record > - // 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 == 0) { > - Status = EFI_ABORTED; > - } else { > - ASSERT (NewPacket != NULL); > - SelectAd = &Private->OfferBuffer[Private->SelectIndex - > 1].Dhcp6.Packet.Offer; > - *NewPacket = AllocateZeroPool (SelectAd->Size); > - if (*NewPacket == 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 record > + // 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 == 0) { > + Status = EFI_ABORTED; > + } else { > + ASSERT (NewPacket != NULL); > + SelectAd = &Private->OfferBuffer[Private->SelectIndex - > 1].Dhcp6.Packet.Offer; > + *NewPacket = AllocateZeroPool (SelectAd->Size); > + if (*NewPacket == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + CopyMem (*NewPacket, SelectAd, SelectAd->Size); > + } > + break; > > - default: > - break; > + default: > + break; > } > > 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 <Protocol/LoadFile.h> > +#include <Protocol/HttpBootCallback.h> > > // > // 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 \ > + ) > > 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; > > // > // 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" > > /** > + 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 > succesfully. > + @retval Others Failed to install HTTP Boot Callback Protocol. > + > +**/ > +EFI_STATUS > +HttpBootInstallCallback ( > + IN HTTP_BOOT_PRIVATE_DATA *Private > + ) > +{ > + EFI_STATUS Status; > + EFI_HANDLE ControllerHandle; > + > + if (!Private->UsingIpv6) { > + ControllerHandle = Private->Ip4Nic->Controller; > + } else { > + ControllerHandle = Private->Ip6Nic->Controller; > + } > + > + // > + // Check whether gEfiHttpBootCallbackProtocolGuid already installed. > + // > + Status = gBS->HandleProtocol ( > + ControllerHandle, > + &gEfiHttpBootCallbackProtocolGuid, > + (VOID **) &Private->HttpBootCallback > + ); > + if (Status == EFI_UNSUPPORTED) { > + > + CopyMem ( > + &Private->LoadFileCallback, > + &gHttpBootDxeHttpBootCallback, > + sizeof (EFI_HTTP_BOOT_CALLBACK_PROTOCOL) > + ); > + > + // > + // Install a default callback if user didn't offer one. > + // > + Status = gBS->InstallProtocolInterface ( > + &ControllerHandle, > + &gEfiHttpBootCallbackProtocolGuid, > + EFI_NATIVE_INTERFACE, > + &Private->LoadFileCallback > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + Private->HttpBootCallback = &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 == &Private->LoadFileCallback) { > + gBS->UninstallProtocolInterface ( > + Private->Controller, > + &gEfiHttpBootCallbackProtocolGuid, > + &Private->HttpBootCallback > + ); > + Private->HttpBootCallback = NULL; > + } > +} > + > +/** > Enable the use of UEFI HTTP boot function. > > If the driver has already been started but not satisfy the requirement (IP > stack and > @@ -144,6 +222,7 @@ HttpBootStart ( > } > } > Private->Started = TRUE; > + Print (L"\n>>Start HTTP Boot over IPv%d", Private->UsingIpv6 ? 6 : 4); > > return EFI_SUCCESS; > } > @@ -237,7 +316,10 @@ HttpBootLoadFile ( > return EFI_NOT_STARTED; > } > > - Status = EFI_DEVICE_ERROR; > + Status = HttpBootInstallCallback (Private); > + if (EFI_ERROR(Status)) { > + goto ON_EXIT; > + } > > if (Private->BootFileUri == NULL) { > // > @@ -245,7 +327,7 @@ HttpBootLoadFile ( > // > Status = HttpBootDiscoverBootInfo (Private); > if (EFI_ERROR (Status)) { > - return Status; > + goto ON_EXIT; > } > } > > @@ -255,7 +337,7 @@ HttpBootLoadFile ( > // > Status = HttpBootCreateHttpIo (Private); > if (EFI_ERROR (Status)) { > - return Status; > + goto ON_EXIT; > } > } > > @@ -287,7 +369,7 @@ HttpBootLoadFile ( > &Private->ImageType > ); > if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) { > - return Status; > + goto ON_EXIT; > } > } > } > @@ -295,19 +377,24 @@ HttpBootLoadFile ( > if (*BufferSize < Private->BootFileSize) { > *BufferSize = Private->BootFileSize; > *ImageType = Private->ImageType; > - return EFI_BUFFER_TOO_SMALL; > + Status = EFI_BUFFER_TOO_SMALL; > + goto ON_EXIT; > } > > // > // Load the boot file into Buffer > // > - return HttpBootGetBootFile ( > - Private, > - FALSE, > - BufferSize, > - Buffer, > - ImageType > - ); > + Status = HttpBootGetBootFile ( > + Private, > + FALSE, > + BufferSize, > + Buffer, > + ImageType > + ); > + > +ON_EXIT: > + HttpBootUninstallCallback (Private); > + return Status; > } > > /** > @@ -520,3 +607,113 @@ GLOBAL_REMOVE_IF_UNREFERENCED > EFI_LOAD_FILE_PROTOCOL gHttpBootDxeLoadFile = { > HttpBootDxeLoadFile > }; > + > +/** > + Callback function that is invoked when the HTTP Boot driver is about 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 > format of the buffer pointed > + to by Data. Due to the polling nature of 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_PROTOCOL instance. > + @param[in] DataType The event that occurs in the current state. > + @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 pointed > to > by Data. > + @param[in] Data A pointer to the buffer of data, the data > 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 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 = > HTTP_BOOT_PRIVATE_DATA_FROM_CALLBACK_PROTOCOL(This); > + > + switch (DataType) { > + case HttpBootDhcp4: > + case HttpBootDhcp6: > + Print (L"."); > + break; > + > + case HttpBootHttpRequest: > + if (Data != NULL) { > + HttpMessage = (EFI_HTTP_MESSAGE *) Data; > + if (HttpMessage->Data.Request->Method == HttpMethodGet && > + HttpMessage->Data.Request->Url != NULL) { > + Print (L"\n URI: %s\n", HttpMessage->Data.Request->Url); > + } > + } > + break; > + > + case HttpBootHttpResponse: > + if (Data != NULL) { > + HttpMessage = (EFI_HTTP_MESSAGE *) Data; > + HttpHeader = HttpFindHeader ( > + HttpMessage->HeaderCount, > + HttpMessage->Headers, > + HTTP_HEADER_CONTENT_LENGTH > + ); > + if (HttpHeader != NULL) { > + Private->FileSize = AsciiStrDecimalToUintn (HttpHeader->FieldValue); > + Private->ReceivedSize = 0; > + Private->Percentage = 0; > + } > + } > + break; > + > + case HttpBootHttpEntityBody: > + if (DataLength != 0) { > + if (Private->FileSize != 0) { > + // > + // We already know the file size, print in percentage format. > + // > + if (Private->ReceivedSize == 0) { > + Print (L" File Size: %lu\n", Private->FileSize); > + } > + Private->ReceivedSize += DataLength; > + Percentage = (UINT32) DivU64x64Remainder (MultU64x32 (Private- > >ReceivedSize, 100), Private->FileSize, NULL); > + if (Private->Percentage != Percentage) { > + Private->Percentage = 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 += 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 = { > + 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 > ); > > +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 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. > > @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 = Controller; > HttpIo->IpVersion = IpVersion; > HttpIo->Http = Http; > + HttpIo->Callback = Callback; > + HttpIo->Context = Context; > > ZeroMem (&HttpConfigData, sizeof (EFI_HTTP_CONFIG_DATA)); > HttpConfigData.HttpVersion = HttpVersion11; > @@ -908,6 +915,17 @@ HttpIoSendRequest ( > HttpIo->ReqToken.Message->BodyLength = BodyLength; > HttpIo->ReqToken.Message->Body = Body; > > + if (HttpIo->Callback != NULL) { > + Status = 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 = FALSE; > } > > + if (!EFI_ERROR (HttpIo->RspToken.Status) && HttpIo->Callback != NULL) { > + Status = 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 > ); > > +/// > +/// 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 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. > + > + @retval EFI_SUCCESS Tells the HttpIo to continue the HTTP process. > + @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 { > > EFI_HTTP_PROTOCOL *Http; > > + 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. > > @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 > ); > > -- > 1.9.5.msysgit.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel