2 The implementation of EFI_LOAD_FILE_PROTOCOL for UEFI HTTP boot.
4 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available under
6 the terms and conditions of the BSD License that accompanies this distribution.
7 The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "HttpBootDxe.h"
18 Enable the use of UEFI HTTP boot function.
20 @param[in] Private The pointer to the driver's private data.
22 @retval EFI_SUCCESS HTTP boot was successfully enabled.
23 @retval EFI_INVALID_PARAMETER Private is NULL.
24 @retval EFI_ALREADY_STARTED The driver is already in started state.
29 IN HTTP_BOOT_PRIVATE_DATA
*Private
34 if (Private
== NULL
) {
35 return EFI_INVALID_PARAMETER
;
38 if (Private
->Started
) {
39 return EFI_ALREADY_STARTED
;
42 if (!Private
->UsingIpv6
) {
44 // Init the content of cached DHCP offer list.
46 ZeroMem (Private
->OfferBuffer
, sizeof (Private
->OfferBuffer
));
47 for (Index
= 0; Index
< HTTP_BOOT_OFFER_MAX_NUM
; Index
++) {
48 Private
->OfferBuffer
[Index
].Dhcp4
.Packet
.Offer
.Size
= HTTP_BOOT_DHCP4_PACKET_MAX_SIZE
;
54 Private
->Started
= TRUE
;
60 Attempt to complete a DHCPv4 D.O.R.A sequence to retrieve the boot resource information.
62 @param[in] Private The pointer to the driver's private data.
64 @retval EFI_SUCCESS Boot info was successfully retrieved.
65 @retval EFI_INVALID_PARAMETER Private is NULL.
66 @retval EFI_NOT_STARTED The driver is in stopped state.
67 @retval EFI_DEVICE_ERROR An unexpected network error occurred.
68 @retval Others Other errors as indicated.
73 IN HTTP_BOOT_PRIVATE_DATA
*Private
78 if (Private
== NULL
) {
79 return EFI_INVALID_PARAMETER
;
82 if (!Private
->Started
) {
83 return EFI_NOT_STARTED
;
86 Status
= EFI_DEVICE_ERROR
;
88 if (!Private
->UsingIpv6
) {
89 Status
= HttpBootDhcp4Dora (Private
);
98 Attempt to download the boot file through HTTP message exchange.
100 @param[in] Private The pointer to the driver's private data.
101 @param[in, out] BufferSize On input the size of Buffer in bytes. On output with a return
102 code of EFI_SUCCESS, the amount of data transferred to
103 Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL,
104 the size of Buffer required to retrieve the requested file.
105 @param[in] Buffer The memory buffer to transfer the file to. If Buffer is NULL,
106 then the size of the requested file is returned in
109 @retval EFI_SUCCESS Boot file was loaded successfully.
110 @retval EFI_INVALID_PARAMETER Private is NULL.
111 @retval EFI_NOT_STARTED The driver is in stopped state.
112 @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the boot file. BufferSize has
113 been updated with the size needed to complete the request.
114 @retval EFI_DEVICE_ERROR An unexpected network error occurred.
115 @retval Others Other errors as indicated.
120 IN HTTP_BOOT_PRIVATE_DATA
*Private
,
121 IN OUT UINTN
*BufferSize
,
122 IN VOID
*Buffer OPTIONAL
127 if (Private
== NULL
) {
128 return EFI_INVALID_PARAMETER
;
131 if (!Private
->Started
) {
132 return EFI_NOT_STARTED
;
135 Status
= EFI_DEVICE_ERROR
;
137 if (Private
->BootFileUri
== NULL
) {
139 // Parse the cached offer to get the boot file URL first.
141 Status
= HttpBootDiscoverBootInfo (Private
);
142 if (EFI_ERROR (Status
)) {
147 if (!Private
->HttpCreated
) {
149 // Create HTTP child.
151 Status
= HttpBootCreateHttpIo (Private
);
152 if (EFI_ERROR (Status
)) {
157 if (Private
->BootFileSize
== 0) {
159 // Discover the information about the bootfile if we haven't.
163 // Try to use HTTP HEAD method.
165 Status
= HttpBootGetBootFile (
168 &Private
->BootFileSize
,
171 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
173 // Failed to get file size by HEAD method, may be trunked encoding, try HTTP GET method.
175 ASSERT (Private
->BootFileSize
== 0);
176 Status
= HttpBootGetBootFile (
179 &Private
->BootFileSize
,
182 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
188 if (*BufferSize
< Private
->BootFileSize
) {
189 *BufferSize
= Private
->BootFileSize
;
190 return EFI_BUFFER_TOO_SMALL
;
194 // Load the boot file into Buffer
196 return HttpBootGetBootFile (
205 Disable the use of UEFI HTTP boot function.
207 @param[in] Private The pointer to the driver's private data.
209 @retval EFI_SUCCESS HTTP boot was successfully disabled.
210 @retval EFI_NOT_STARTED The driver is already in stopped state.
211 @retval EFI_INVALID_PARAMETER Private is NULL.
212 @retval Others Unexpected error when stop the function.
217 IN HTTP_BOOT_PRIVATE_DATA
*Private
222 if (Private
== NULL
) {
223 return EFI_INVALID_PARAMETER
;
226 if (!Private
->Started
) {
227 return EFI_NOT_STARTED
;
230 if (Private
->HttpCreated
) {
231 HttpIoDestroyIo (&Private
->HttpIo
);
232 Private
->HttpCreated
= FALSE
;
235 Private
->Started
= FALSE
;
236 ZeroMem (&Private
->StationIp
, sizeof (EFI_IP_ADDRESS
));
237 ZeroMem (&Private
->SubnetMask
, sizeof (EFI_IP_ADDRESS
));
238 ZeroMem (&Private
->GatewayIp
, sizeof (EFI_IP_ADDRESS
));
240 Private
->BootFileUri
= NULL
;
241 Private
->BootFileUriParser
= NULL
;
242 Private
->BootFileSize
= 0;
243 Private
->SelectIndex
= 0;
244 Private
->SelectProxyType
= HttpOfferTypeMax
;
246 if (!Private
->UsingIpv6
) {
248 // Stop and release the DHCP4 child.
250 Private
->Dhcp4
->Stop (Private
->Dhcp4
);
251 Private
->Dhcp4
->Configure (Private
->Dhcp4
, NULL
);
253 for (Index
= 0; Index
< HTTP_BOOT_OFFER_MAX_NUM
; Index
++) {
254 if (Private
->OfferBuffer
[Index
].Dhcp4
.UriParser
) {
255 HttpUrlFreeParser (Private
->OfferBuffer
[Index
].Dhcp4
.UriParser
);
262 ZeroMem (Private
->OfferBuffer
, sizeof (Private
->OfferBuffer
));
263 Private
->OfferNum
= 0;
264 ZeroMem (Private
->OfferCount
, sizeof (Private
->OfferCount
));
265 ZeroMem (Private
->OfferIndex
, sizeof (Private
->OfferIndex
));
271 Causes the driver to load a specified file.
273 @param This Protocol instance pointer.
274 @param FilePath The device specific path of the file to load.
275 @param BootPolicy If TRUE, indicates that the request originates from the
276 boot manager is attempting to load FilePath as a boot
277 selection. If FALSE, then FilePath must match as exact file
279 @param BufferSize On input the size of Buffer in bytes. On output with a return
280 code of EFI_SUCCESS, the amount of data transferred to
281 Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL,
282 the size of Buffer required to retrieve the requested file.
283 @param Buffer The memory buffer to transfer the file to. IF Buffer is NULL,
284 then the size of the requested file is returned in
287 @retval EFI_SUCCESS The file was loaded.
288 @retval EFI_UNSUPPORTED The device does not support the provided BootPolicy
289 @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or
291 @retval EFI_NO_MEDIA No medium was present to load the file.
292 @retval EFI_DEVICE_ERROR The file was not loaded due to a device error.
293 @retval EFI_NO_RESPONSE The remote system did not respond.
294 @retval EFI_NOT_FOUND The file was not found.
295 @retval EFI_ABORTED The file load process was manually cancelled.
296 @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.
297 BufferSize has been updated with the size needed to complete
303 HttpBootDxeLoadFile (
304 IN EFI_LOAD_FILE_PROTOCOL
*This
,
305 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
306 IN BOOLEAN BootPolicy
,
307 IN OUT UINTN
*BufferSize
,
308 IN VOID
*Buffer OPTIONAL
311 HTTP_BOOT_PRIVATE_DATA
*Private
;
312 BOOLEAN MediaPresent
;
315 if (This
== NULL
|| BufferSize
== NULL
) {
316 return EFI_INVALID_PARAMETER
;
320 // Only support BootPolicy
323 return EFI_UNSUPPORTED
;
326 Private
= HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE (This
);
329 // Check media status before HTTP boot start
332 NetLibDetectMedia (Private
->Controller
, &MediaPresent
);
338 // Initialize HTTP boot and load the boot file.
340 Status
= HttpBootStart (Private
);
341 if (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
) {
342 Status
= HttpBootLoadFile (Private
, BufferSize
, Buffer
);
345 if (Status
!= EFI_SUCCESS
&& Status
!= EFI_BUFFER_TOO_SMALL
) {
346 HttpBootStop (Private
);
349 // Stop and release the DHCP4 child.
351 Private
->Dhcp4
->Stop (Private
->Dhcp4
);
352 Private
->Dhcp4
->Configure (Private
->Dhcp4
, NULL
);
359 /// Load File Protocol instance
361 GLOBAL_REMOVE_IF_UNREFERENCED
362 EFI_LOAD_FILE_PROTOCOL gHttpBootDxeLoadFile
= {