2 The implementation of EFI_LOAD_FILE_PROTOCOL for UEFI HTTP boot.
4 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "HttpBootDxe.h"
13 Install HTTP Boot Callback Protocol if not installed before.
15 @param[in] Private Pointer to HTTP Boot private data.
17 @retval EFI_SUCCESS HTTP Boot Callback Protocol installed successfully.
18 @retval Others Failed to install HTTP Boot Callback Protocol.
22 HttpBootInstallCallback (
23 IN HTTP_BOOT_PRIVATE_DATA
*Private
27 EFI_HANDLE ControllerHandle
;
29 if (!Private
->UsingIpv6
) {
30 ControllerHandle
= Private
->Ip4Nic
->Controller
;
32 ControllerHandle
= Private
->Ip6Nic
->Controller
;
36 // Check whether gEfiHttpBootCallbackProtocolGuid already installed.
38 Status
= gBS
->HandleProtocol (
40 &gEfiHttpBootCallbackProtocolGuid
,
41 (VOID
**)&Private
->HttpBootCallback
43 if (Status
== EFI_UNSUPPORTED
) {
45 &Private
->LoadFileCallback
,
46 &gHttpBootDxeHttpBootCallback
,
47 sizeof (EFI_HTTP_BOOT_CALLBACK_PROTOCOL
)
51 // Install a default callback if user didn't offer one.
53 Status
= gBS
->InstallProtocolInterface (
55 &gEfiHttpBootCallbackProtocolGuid
,
57 &Private
->LoadFileCallback
59 if (EFI_ERROR (Status
)) {
63 Private
->HttpBootCallback
= &Private
->LoadFileCallback
;
70 Uninstall HTTP Boot Callback Protocol if it's installed by this driver.
72 @param[in] Private Pointer to HTTP Boot private data.
76 HttpBootUninstallCallback (
77 IN HTTP_BOOT_PRIVATE_DATA
*Private
80 if (Private
->HttpBootCallback
== &Private
->LoadFileCallback
) {
81 gBS
->UninstallProtocolInterface (
83 &gEfiHttpBootCallbackProtocolGuid
,
84 &Private
->HttpBootCallback
86 Private
->HttpBootCallback
= NULL
;
91 Enable the use of UEFI HTTP boot function.
93 If the driver has already been started but not satisfy the requirement (IP stack and
94 specified boot file path), this function will stop the driver and start it again.
96 @param[in] Private The pointer to the driver's private data.
97 @param[in] UsingIpv6 Specifies the type of IP addresses that are to be
98 used during the session that is being started.
99 Set to TRUE for IPv6, and FALSE for IPv4.
100 @param[in] FilePath The device specific path of the file to load.
102 @retval EFI_SUCCESS HTTP boot was successfully enabled.
103 @retval EFI_INVALID_PARAMETER Private is NULL or FilePath is NULL.
104 @retval EFI_INVALID_PARAMETER The FilePath doesn't contain a valid URI device path node.
105 @retval EFI_ALREADY_STARTED The driver is already in started state.
106 @retval EFI_OUT_OF_RESOURCES There are not enough resources.
111 IN HTTP_BOOT_PRIVATE_DATA
*Private
,
112 IN BOOLEAN UsingIpv6
,
113 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
122 if ((Private
== NULL
) || (FilePath
== NULL
)) {
123 return EFI_INVALID_PARAMETER
;
127 // Check the URI in the input FilePath, in order to see whether it is
128 // required to boot from a new specified boot file.
130 Status
= HttpBootParseFilePath (FilePath
, &Uri
);
131 if (EFI_ERROR (Status
)) {
132 return EFI_INVALID_PARAMETER
;
136 // Check whether we need to stop and restart the HTTP boot driver.
138 if (Private
->Started
) {
140 // Restart is needed in 2 cases:
141 // 1. Http boot driver has already been started but not on the required IP stack.
142 // 2. The specified boot file URI in FilePath is different with the one we have
145 if ((UsingIpv6
!= Private
->UsingIpv6
) ||
146 ((Uri
!= NULL
) && (AsciiStrCmp (Private
->BootFileUri
, Uri
) != 0)))
149 // Restart is required, first stop then continue this start function.
151 Status
= HttpBootStop (Private
);
152 if (EFI_ERROR (Status
)) {
161 // Restart is not required.
167 return EFI_ALREADY_STARTED
;
172 // Detect whether using ipv6 or not, and set it to the private data.
174 if (UsingIpv6
&& (Private
->Ip6Nic
!= NULL
)) {
175 Private
->UsingIpv6
= TRUE
;
176 } else if (!UsingIpv6
&& (Private
->Ip4Nic
!= NULL
)) {
177 Private
->UsingIpv6
= FALSE
;
183 return EFI_UNSUPPORTED
;
187 // Record the specified URI and prepare the URI parser if needed.
189 Private
->FilePathUri
= Uri
;
190 if (Private
->FilePathUri
!= NULL
) {
191 Status
= HttpParseUrl (
192 Private
->FilePathUri
,
193 (UINT32
)AsciiStrLen (Private
->FilePathUri
),
195 &Private
->FilePathUriParser
197 if (EFI_ERROR (Status
)) {
198 FreePool (Private
->FilePathUri
);
204 // Init the content of cached DHCP offer list.
206 ZeroMem (Private
->OfferBuffer
, sizeof (Private
->OfferBuffer
));
207 if (!Private
->UsingIpv6
) {
208 for (Index
= 0; Index
< HTTP_BOOT_OFFER_MAX_NUM
; Index
++) {
209 Private
->OfferBuffer
[Index
].Dhcp4
.Packet
.Offer
.Size
= HTTP_CACHED_DHCP4_PACKET_MAX_SIZE
;
212 for (Index
= 0; Index
< HTTP_BOOT_OFFER_MAX_NUM
; Index
++) {
213 Private
->OfferBuffer
[Index
].Dhcp6
.Packet
.Offer
.Size
= HTTP_CACHED_DHCP6_PACKET_MAX_SIZE
;
217 if (Private
->UsingIpv6
) {
219 // Set Ip6 policy to Automatic to start the Ip6 router discovery.
221 Status
= HttpBootSetIp6Policy (Private
);
222 if (EFI_ERROR (Status
)) {
227 Private
->Started
= TRUE
;
228 Print (L
"\n>>Start HTTP Boot over IPv%d", Private
->UsingIpv6
? 6 : 4);
234 Attempt to complete a DHCPv4 D.O.R.A or DHCPv6 S.R.A.A sequence to retrieve the boot resource information.
236 @param[in] Private The pointer to the driver's private data.
238 @retval EFI_SUCCESS Boot info was successfully retrieved.
239 @retval EFI_INVALID_PARAMETER Private is NULL.
240 @retval EFI_NOT_STARTED The driver is in stopped state.
241 @retval EFI_DEVICE_ERROR An unexpected network error occurred.
242 @retval Others Other errors as indicated.
247 IN HTTP_BOOT_PRIVATE_DATA
*Private
252 if (Private
== NULL
) {
253 return EFI_INVALID_PARAMETER
;
256 if (!Private
->Started
) {
257 return EFI_NOT_STARTED
;
260 Status
= EFI_DEVICE_ERROR
;
262 if (!Private
->UsingIpv6
) {
264 // Start D.O.R.A process to get a IPv4 address and other boot information.
266 Status
= HttpBootDhcp4Dora (Private
);
269 // Start S.A.R.R process to get a IPv6 address and other boot information.
271 Status
= HttpBootDhcp6Sarr (Private
);
278 Attempt to download the boot file through HTTP message exchange.
280 @param[in] Private The pointer to the driver's private data.
281 @param[in, out] BufferSize On input the size of Buffer in bytes. On output with a return
282 code of EFI_SUCCESS, the amount of data transferred to
283 Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL,
284 the size of Buffer required to retrieve the requested file.
285 @param[in] Buffer The memory buffer to transfer the file to. If Buffer is NULL,
286 then the size of the requested file is returned in
288 @param[out] ImageType The image type of the downloaded file.
290 @retval EFI_SUCCESS Boot file was loaded successfully.
291 @retval EFI_INVALID_PARAMETER Private is NULL, or ImageType is NULL, or BufferSize is NULL.
292 @retval EFI_INVALID_PARAMETER *BufferSize is not zero, and Buffer is NULL.
293 @retval EFI_NOT_STARTED The driver is in stopped state.
294 @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the boot file. BufferSize has
295 been updated with the size needed to complete the request.
296 @retval EFI_DEVICE_ERROR An unexpected network error occurred.
297 @retval Others Other errors as indicated.
302 IN HTTP_BOOT_PRIVATE_DATA
*Private
,
303 IN OUT UINTN
*BufferSize
,
304 IN VOID
*Buffer OPTIONAL
,
305 OUT HTTP_BOOT_IMAGE_TYPE
*ImageType
310 if ((Private
== NULL
) || (ImageType
== NULL
) || (BufferSize
== NULL
)) {
311 return EFI_INVALID_PARAMETER
;
314 if ((*BufferSize
!= 0) && (Buffer
== NULL
)) {
315 return EFI_INVALID_PARAMETER
;
318 if (!Private
->Started
) {
319 return EFI_NOT_STARTED
;
322 Status
= HttpBootInstallCallback (Private
);
323 if (EFI_ERROR (Status
)) {
327 if (Private
->BootFileUri
== NULL
) {
329 // Parse the cached offer to get the boot file URL first.
331 Status
= HttpBootDiscoverBootInfo (Private
);
332 if (EFI_ERROR (Status
)) {
333 AsciiPrint ("\n Error: Could not retrieve NBP file size from HTTP server.\n");
338 if (!Private
->HttpCreated
) {
340 // Create HTTP child.
342 Status
= HttpBootCreateHttpIo (Private
);
343 if (EFI_ERROR (Status
)) {
348 if (Private
->BootFileSize
== 0) {
350 // Discover the information about the bootfile if we haven't.
354 // Try to use HTTP HEAD method.
356 Status
= HttpBootGetBootFile (
359 &Private
->BootFileSize
,
363 if ((Private
->AuthData
!= NULL
) && (Status
== EFI_ACCESS_DENIED
)) {
365 // Try to use HTTP HEAD method again since the Authentication information is provided.
367 Status
= HttpBootGetBootFile (
370 &Private
->BootFileSize
,
374 } else if ((EFI_ERROR (Status
)) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
376 // Failed to get file size by HEAD method, may be trunked encoding, try HTTP GET method.
378 ASSERT (Private
->BootFileSize
== 0);
379 Status
= HttpBootGetBootFile (
382 &Private
->BootFileSize
,
386 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
387 AsciiPrint ("\n Error: Could not retrieve NBP file size from HTTP server.\n");
393 if (*BufferSize
< Private
->BootFileSize
) {
394 *BufferSize
= Private
->BootFileSize
;
395 *ImageType
= Private
->ImageType
;
396 Status
= EFI_BUFFER_TOO_SMALL
;
401 // Load the boot file into Buffer
403 Status
= HttpBootGetBootFile (
412 HttpBootUninstallCallback (Private
);
414 if (EFI_ERROR (Status
)) {
415 if (Status
== EFI_ACCESS_DENIED
) {
416 AsciiPrint ("\n Error: Could not establish connection with HTTP server.\n");
417 } else if ((Status
== EFI_BUFFER_TOO_SMALL
) && (Buffer
!= NULL
)) {
418 AsciiPrint ("\n Error: Buffer size is smaller than the requested file.\n");
419 } else if (Status
== EFI_OUT_OF_RESOURCES
) {
420 AsciiPrint ("\n Error: Could not allocate I/O buffers.\n");
421 } else if (Status
== EFI_DEVICE_ERROR
) {
422 AsciiPrint ("\n Error: Network device error.\n");
423 } else if (Status
== EFI_TIMEOUT
) {
424 AsciiPrint ("\n Error: Server response timeout.\n");
425 } else if (Status
== EFI_ABORTED
) {
426 AsciiPrint ("\n Error: Remote boot cancelled.\n");
427 } else if (Status
!= EFI_BUFFER_TOO_SMALL
) {
428 AsciiPrint ("\n Error: Unexpected network error.\n");
436 Disable the use of UEFI HTTP boot function.
438 @param[in] Private The pointer to the driver's private data.
440 @retval EFI_SUCCESS HTTP boot was successfully disabled.
441 @retval EFI_NOT_STARTED The driver is already in stopped state.
442 @retval EFI_INVALID_PARAMETER Private is NULL.
443 @retval Others Unexpected error when stop the function.
448 IN HTTP_BOOT_PRIVATE_DATA
*Private
453 if (Private
== NULL
) {
454 return EFI_INVALID_PARAMETER
;
457 if (!Private
->Started
) {
458 return EFI_NOT_STARTED
;
461 if (Private
->HttpCreated
) {
462 HttpIoDestroyIo (&Private
->HttpIo
);
463 Private
->HttpCreated
= FALSE
;
466 Private
->Started
= FALSE
;
467 ZeroMem (&Private
->StationIp
, sizeof (EFI_IP_ADDRESS
));
468 ZeroMem (&Private
->SubnetMask
, sizeof (EFI_IP_ADDRESS
));
469 ZeroMem (&Private
->GatewayIp
, sizeof (EFI_IP_ADDRESS
));
471 Private
->BootFileUri
= NULL
;
472 Private
->BootFileUriParser
= NULL
;
473 Private
->BootFileSize
= 0;
474 Private
->SelectIndex
= 0;
475 Private
->SelectProxyType
= HttpOfferTypeMax
;
477 if (!Private
->UsingIpv6
) {
479 // Stop and release the DHCP4 child.
481 Private
->Dhcp4
->Stop (Private
->Dhcp4
);
482 Private
->Dhcp4
->Configure (Private
->Dhcp4
, NULL
);
484 for (Index
= 0; Index
< HTTP_BOOT_OFFER_MAX_NUM
; Index
++) {
485 if (Private
->OfferBuffer
[Index
].Dhcp4
.UriParser
) {
486 HttpUrlFreeParser (Private
->OfferBuffer
[Index
].Dhcp4
.UriParser
);
491 // Stop and release the DHCP6 child.
493 Private
->Dhcp6
->Stop (Private
->Dhcp6
);
494 Private
->Dhcp6
->Configure (Private
->Dhcp6
, NULL
);
496 for (Index
= 0; Index
< HTTP_BOOT_OFFER_MAX_NUM
; Index
++) {
497 if (Private
->OfferBuffer
[Index
].Dhcp6
.UriParser
) {
498 HttpUrlFreeParser (Private
->OfferBuffer
[Index
].Dhcp6
.UriParser
);
503 if (Private
->AuthData
!= NULL
) {
504 FreePool (Private
->AuthData
);
505 Private
->AuthData
= NULL
;
508 if (Private
->AuthScheme
!= NULL
) {
509 FreePool (Private
->AuthScheme
);
510 Private
->AuthScheme
= NULL
;
513 if (Private
->DnsServerIp
!= NULL
) {
514 FreePool (Private
->DnsServerIp
);
515 Private
->DnsServerIp
= NULL
;
518 if (Private
->FilePathUri
!= NULL
) {
519 FreePool (Private
->FilePathUri
);
520 HttpUrlFreeParser (Private
->FilePathUriParser
);
521 Private
->FilePathUri
= NULL
;
522 Private
->FilePathUriParser
= NULL
;
525 ZeroMem (Private
->OfferBuffer
, sizeof (Private
->OfferBuffer
));
526 Private
->OfferNum
= 0;
527 ZeroMem (Private
->OfferCount
, sizeof (Private
->OfferCount
));
528 ZeroMem (Private
->OfferIndex
, sizeof (Private
->OfferIndex
));
530 HttpBootFreeCacheList (Private
);
536 Causes the driver to load a specified file.
538 @param This Protocol instance pointer.
539 @param FilePath The device specific path of the file to load.
540 @param BootPolicy If TRUE, indicates that the request originates from the
541 boot manager is attempting to load FilePath as a boot
542 selection. If FALSE, then FilePath must match as exact file
544 @param BufferSize On input the size of Buffer in bytes. On output with a return
545 code of EFI_SUCCESS, the amount of data transferred to
546 Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL,
547 the size of Buffer required to retrieve the requested file.
548 @param Buffer The memory buffer to transfer the file to. IF Buffer is NULL,
549 then the size of the requested file is returned in
552 @retval EFI_SUCCESS The file was loaded.
553 @retval EFI_UNSUPPORTED The device does not support the provided BootPolicy
554 @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or
556 @retval EFI_NO_MEDIA No medium was present to load the file.
557 @retval EFI_DEVICE_ERROR The file was not loaded due to a device error.
558 @retval EFI_NO_RESPONSE The remote system did not respond.
559 @retval EFI_NOT_FOUND The file was not found.
560 @retval EFI_ABORTED The file load process was manually cancelled.
561 @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.
562 BufferSize has been updated with the size needed to complete
568 HttpBootDxeLoadFile (
569 IN EFI_LOAD_FILE_PROTOCOL
*This
,
570 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
571 IN BOOLEAN BootPolicy
,
572 IN OUT UINTN
*BufferSize
,
573 IN VOID
*Buffer OPTIONAL
576 HTTP_BOOT_PRIVATE_DATA
*Private
;
577 HTTP_BOOT_VIRTUAL_NIC
*VirtualNic
;
578 EFI_STATUS MediaStatus
;
581 HTTP_BOOT_IMAGE_TYPE ImageType
;
583 if ((This
== NULL
) || (BufferSize
== NULL
) || (FilePath
== NULL
)) {
584 return EFI_INVALID_PARAMETER
;
588 // Only support BootPolicy
591 return EFI_UNSUPPORTED
;
594 VirtualNic
= HTTP_BOOT_VIRTUAL_NIC_FROM_LOADFILE (This
);
595 Private
= VirtualNic
->Private
;
598 // Check media status before HTTP boot start
600 MediaStatus
= EFI_SUCCESS
;
601 NetLibDetectMediaWaitTimeout (Private
->Controller
, HTTP_BOOT_CHECK_MEDIA_WAITING_TIME
, &MediaStatus
);
602 if (MediaStatus
!= EFI_SUCCESS
) {
603 AsciiPrint ("\n Error: Could not detect network connection.\n");
608 // Check whether the virtual nic is using IPv6 or not.
611 if (VirtualNic
== Private
->Ip6Nic
) {
616 // Initialize HTTP boot.
618 Status
= HttpBootStart (Private
, UsingIpv6
, FilePath
);
619 if ((Status
!= EFI_SUCCESS
) && (Status
!= EFI_ALREADY_STARTED
)) {
624 // Load the boot file.
626 ImageType
= ImageTypeMax
;
627 Status
= HttpBootLoadFile (Private
, BufferSize
, Buffer
, &ImageType
);
628 if (EFI_ERROR (Status
)) {
629 if ((Status
== EFI_BUFFER_TOO_SMALL
) && ((ImageType
== ImageTypeVirtualCd
) || (ImageType
== ImageTypeVirtualDisk
))) {
630 Status
= EFI_WARN_FILE_SYSTEM
;
631 } else if (Status
!= EFI_BUFFER_TOO_SMALL
) {
632 HttpBootStop (Private
);
639 // Register the RAM Disk to the system if needed.
641 if ((ImageType
== ImageTypeVirtualCd
) || (ImageType
== ImageTypeVirtualDisk
)) {
642 Status
= HttpBootRegisterRamDisk (Private
, *BufferSize
, Buffer
, ImageType
);
643 if (!EFI_ERROR (Status
)) {
644 Status
= EFI_WARN_FILE_SYSTEM
;
646 AsciiPrint ("\n Error: Could not register RAM disk to the system.\n");
651 // Stop the HTTP Boot service after the boot image is downloaded.
653 HttpBootStop (Private
);
658 /// Load File Protocol instance
660 GLOBAL_REMOVE_IF_UNREFERENCED
661 EFI_LOAD_FILE_PROTOCOL gHttpBootDxeLoadFile
= {
666 Callback function that is invoked when the HTTP Boot driver is about to transmit or has received a
669 This function is invoked when the HTTP Boot driver is about to transmit or has received packet.
670 Parameters DataType and Received specify the type of event and the format of the buffer pointed
671 to by Data. Due to the polling nature of UEFI device drivers, this callback function should not
672 execute for more than 5 ms.
673 The returned status code determines the behavior of the HTTP Boot driver.
675 @param[in] This Pointer to the EFI_HTTP_BOOT_CALLBACK_PROTOCOL instance.
676 @param[in] DataType The event that occurs in the current state.
677 @param[in] Received TRUE if the callback is being invoked due to a receive event.
678 FALSE if the callback is being invoked due to a transmit event.
679 @param[in] DataLength The length in bytes of the buffer pointed to by Data.
680 @param[in] Data A pointer to the buffer of data, the data type is specified by
683 @retval EFI_SUCCESS Tells the HTTP Boot driver to continue the HTTP Boot process.
684 @retval EFI_ABORTED Tells the HTTP Boot driver to abort the current HTTP Boot process.
689 IN EFI_HTTP_BOOT_CALLBACK_PROTOCOL
*This
,
690 IN EFI_HTTP_BOOT_CALLBACK_DATA_TYPE DataType
,
692 IN UINT32 DataLength
,
693 IN VOID
*Data OPTIONAL
696 EFI_HTTP_MESSAGE
*HttpMessage
;
697 EFI_HTTP_HEADER
*HttpHeader
;
698 HTTP_BOOT_PRIVATE_DATA
*Private
;
701 Private
= HTTP_BOOT_PRIVATE_DATA_FROM_CALLBACK_PROTOCOL (This
);
709 case HttpBootHttpRequest
:
711 HttpMessage
= (EFI_HTTP_MESSAGE
*)Data
;
712 if ((HttpMessage
->Data
.Request
->Method
== HttpMethodGet
) &&
713 (HttpMessage
->Data
.Request
->Url
!= NULL
))
715 Print (L
"\n URI: %s\n", HttpMessage
->Data
.Request
->Url
);
721 case HttpBootHttpResponse
:
723 HttpMessage
= (EFI_HTTP_MESSAGE
*)Data
;
725 if (HttpMessage
->Data
.Response
!= NULL
) {
726 if (HttpBootIsHttpRedirectStatusCode (HttpMessage
->Data
.Response
->StatusCode
)) {
728 // Server indicates the resource has been redirected to a different URL
729 // according to the section 6.4 of RFC7231 and the RFC 7538.
730 // Display the redirect information on the screen.
732 HttpHeader
= HttpFindHeader (
733 HttpMessage
->HeaderCount
,
734 HttpMessage
->Headers
,
737 if (HttpHeader
!= NULL
) {
738 Print (L
"\n HTTP ERROR: Resource Redirected.\n New Location: %a\n", HttpHeader
->FieldValue
);
745 HttpHeader
= HttpFindHeader (
746 HttpMessage
->HeaderCount
,
747 HttpMessage
->Headers
,
748 HTTP_HEADER_CONTENT_LENGTH
750 if (HttpHeader
!= NULL
) {
751 Private
->FileSize
= AsciiStrDecimalToUintn (HttpHeader
->FieldValue
);
752 Private
->ReceivedSize
= 0;
753 Private
->Percentage
= 0;
759 case HttpBootHttpEntityBody
:
760 if (DataLength
!= 0) {
761 if (Private
->FileSize
!= 0) {
763 // We already know the file size, print in percentage format.
765 if (Private
->ReceivedSize
== 0) {
766 Print (L
" File Size: %lu Bytes\n", Private
->FileSize
);
769 Private
->ReceivedSize
+= DataLength
;
770 Percentage
= (UINT32
)DivU64x64Remainder (MultU64x32 (Private
->ReceivedSize
, 100), Private
->FileSize
, NULL
);
771 if (Private
->Percentage
!= Percentage
) {
772 Private
->Percentage
= Percentage
;
773 Print (L
"\r Downloading...%d%%", Percentage
);
777 // In some case we couldn't get the file size from the HTTP header, so we
778 // just print the downloaded file size.
780 Private
->ReceivedSize
+= DataLength
;
781 Print (L
"\r Downloading...%lu Bytes", Private
->ReceivedSize
);
795 /// HTTP Boot Callback Protocol instance
797 GLOBAL_REMOVE_IF_UNREFERENCED
798 EFI_HTTP_BOOT_CALLBACK_PROTOCOL gHttpBootDxeHttpBootCallback
= {