]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/HttpBootDxe/HttpBootSupport.c
NetworkPkg: Handling timeout case in httpboot driver
[mirror_edk2.git] / NetworkPkg / HttpBootDxe / HttpBootSupport.c
CommitLineData
d933e70a
JW
1/** @file\r
2 Support functions implementation for UEFI HTTP boot driver.\r
3\r
072289f4 4Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>\r
f58554fc
GB
5(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
6This program and the accompanying materials are licensed and made available under\r
7the terms and conditions of the BSD License that accompanies this distribution.\r
d933e70a
JW
8The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php. \r
10 \r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "HttpBootDxe.h"\r
17\r
18\r
19/**\r
20 Get the Nic handle using any child handle in the IPv4 stack.\r
21\r
22 @param[in] ControllerHandle Pointer to child handle over IPv4.\r
23\r
24 @return NicHandle The pointer to the Nic handle.\r
25 @return NULL Can't find the Nic handle.\r
26\r
27**/\r
28EFI_HANDLE\r
29HttpBootGetNicByIp4Children (\r
30 IN EFI_HANDLE ControllerHandle\r
31 )\r
32{\r
33 EFI_HANDLE NicHandle;\r
34\r
35 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiHttpProtocolGuid);\r
36 if (NicHandle == NULL) {\r
37 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);\r
38 if (NicHandle == NULL) {\r
39 return NULL;\r
40 }\r
41 }\r
42\r
43 return NicHandle;\r
44}\r
45\r
b659408b
ZL
46/**\r
47 Get the Nic handle using any child handle in the IPv6 stack.\r
48\r
49 @param[in] ControllerHandle Pointer to child handle over IPv6.\r
50\r
51 @return NicHandle The pointer to the Nic handle.\r
52 @return NULL Can't find the Nic handle.\r
53\r
54**/\r
55EFI_HANDLE\r
56HttpBootGetNicByIp6Children (\r
57 IN EFI_HANDLE ControllerHandle\r
58 )\r
59{\r
60 EFI_HANDLE NicHandle;\r
61 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiHttpProtocolGuid);\r
62 if (NicHandle == NULL) {\r
63 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp6ProtocolGuid);\r
64 if (NicHandle == NULL) {\r
65 return NULL;\r
66 }\r
67 }\r
68\r
69 return NicHandle;\r
70}\r
d933e70a
JW
71\r
72/**\r
73 This function is to convert UINTN to ASCII string with the required formatting.\r
74\r
75 @param[in] Number Numeric value to be converted.\r
76 @param[in] Buffer The pointer to the buffer for ASCII string.\r
77 @param[in] Length The length of the required format.\r
78\r
79**/\r
80VOID\r
81HttpBootUintnToAscDecWithFormat (\r
82 IN UINTN Number,\r
83 IN UINT8 *Buffer,\r
84 IN INTN Length\r
85 )\r
86{\r
87 UINTN Remainder;\r
88\r
89 while (Length > 0) {\r
90 Length--;\r
91 Remainder = Number % 10;\r
92 Number /= 10;\r
93 Buffer[Length] = (UINT8) ('0' + Remainder);\r
94 }\r
95}\r
96\r
97/**\r
98 This function is to display the IPv4 address.\r
99\r
100 @param[in] Ip The pointer to the IPv4 address.\r
101\r
102**/\r
103VOID\r
104HttpBootShowIp4Addr (\r
105 IN EFI_IPv4_ADDRESS *Ip\r
106 )\r
107{\r
108 UINTN Index;\r
109\r
110 for (Index = 0; Index < 4; Index++) {\r
111 AsciiPrint ("%d", Ip->Addr[Index]);\r
112 if (Index < 3) {\r
113 AsciiPrint (".");\r
114 }\r
115 }\r
116}\r
117\r
b659408b
ZL
118/**\r
119 This function is to display the IPv6 address.\r
120\r
121 @param[in] Ip The pointer to the IPv6 address.\r
122\r
123**/\r
124VOID\r
125HttpBootShowIp6Addr (\r
126 IN EFI_IPv6_ADDRESS *Ip\r
127 )\r
128{\r
129 UINTN Index;\r
130\r
131 for (Index = 0; Index < 16; Index++) {\r
132\r
133 if (Ip->Addr[Index] != 0) {\r
134 AsciiPrint ("%x", Ip->Addr[Index]);\r
135 }\r
136 Index++;\r
137 if (Index > 15) {\r
138 return;\r
139 }\r
140 if (((Ip->Addr[Index] & 0xf0) == 0) && (Ip->Addr[Index - 1] != 0)) {\r
141 AsciiPrint ("0");\r
142 }\r
143 AsciiPrint ("%x", Ip->Addr[Index]);\r
144 if (Index < 15) {\r
145 AsciiPrint (":");\r
146 }\r
147 }\r
148}\r
149\r
62cae351
ZL
150/**\r
151 This function is to display the HTTP error status.\r
152\r
153 @param[in] StatusCode The status code value in HTTP message.\r
154\r
155**/\r
156VOID\r
157HttpBootPrintErrorMessage (\r
158 EFI_HTTP_STATUS_CODE StatusCode\r
159 )\r
160{\r
161 AsciiPrint ("\n");\r
162\r
163 switch (StatusCode) {\r
164 case HTTP_STATUS_300_MULTIPLE_CHIOCES:\r
165 AsciiPrint ("\n Redirection: 300 Multiple Choices");\r
166 break; \r
167 \r
168 case HTTP_STATUS_301_MOVED_PERMANENTLY:\r
169 AsciiPrint ("\n Redirection: 301 Moved Permanently");\r
170 break; \r
171 \r
172 case HTTP_STATUS_302_FOUND:\r
173 AsciiPrint ("\n Redirection: 302 Found");\r
174 break; \r
175 \r
176 case HTTP_STATUS_303_SEE_OTHER:\r
177 AsciiPrint ("\n Redirection: 303 See Other");\r
178 break; \r
179\r
180 case HTTP_STATUS_304_NOT_MODIFIED:\r
181 AsciiPrint ("\n Redirection: 304 Not Modified");\r
182 break; \r
183\r
184 case HTTP_STATUS_305_USE_PROXY:\r
185 AsciiPrint ("\n Redirection: 305 Use Proxy");\r
186 break; \r
187\r
188 case HTTP_STATUS_307_TEMPORARY_REDIRECT:\r
189 AsciiPrint ("\n Redirection: 307 Temporary Redirect");\r
190 break; \r
191\r
192 case HTTP_STATUS_400_BAD_REQUEST:\r
193 AsciiPrint ("\n Client Error: 400 Bad Request");\r
194 break;\r
195 \r
196 case HTTP_STATUS_401_UNAUTHORIZED:\r
197 AsciiPrint ("\n Client Error: 401 Unauthorized");\r
198 break;\r
199 \r
200 case HTTP_STATUS_402_PAYMENT_REQUIRED:\r
201 AsciiPrint ("\n Client Error: 402 Payment Required");\r
202 break;\r
203\r
204 case HTTP_STATUS_403_FORBIDDEN:\r
205 AsciiPrint ("\n Client Error: 403 Forbidden");\r
206 break;\r
207\r
208 case HTTP_STATUS_404_NOT_FOUND:\r
209 AsciiPrint ("\n Client Error: 404 Not Found");\r
210 break;\r
211\r
212 case HTTP_STATUS_405_METHOD_NOT_ALLOWED:\r
213 AsciiPrint ("\n Client Error: 405 Method Not Allowed");\r
214 break;\r
215\r
216 case HTTP_STATUS_406_NOT_ACCEPTABLE:\r
217 AsciiPrint ("\n Client Error: 406 Not Acceptable");\r
218 break;\r
219\r
220 case HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED:\r
221 AsciiPrint ("\n Client Error: 407 Proxy Authentication Required");\r
222 break;\r
223\r
224 case HTTP_STATUS_408_REQUEST_TIME_OUT:\r
225 AsciiPrint ("\n Client Error: 408 Request Timeout");\r
226 break;\r
227\r
228 case HTTP_STATUS_409_CONFLICT:\r
229 AsciiPrint ("\n Client Error: 409 Conflict");\r
230 break;\r
231\r
232 case HTTP_STATUS_410_GONE:\r
233 AsciiPrint ("\n Client Error: 410 Gone");\r
234 break;\r
235\r
236 case HTTP_STATUS_411_LENGTH_REQUIRED:\r
237 AsciiPrint ("\n Client Error: 411 Length Required");\r
238 break;\r
239\r
240 case HTTP_STATUS_412_PRECONDITION_FAILED:\r
241 AsciiPrint ("\n Client Error: 412 Precondition Failed");\r
242 break;\r
243\r
244 case HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE:\r
245 AsciiPrint ("\n Client Error: 413 Request Entity Too Large");\r
246 break;\r
247\r
248 case HTTP_STATUS_414_REQUEST_URI_TOO_LARGE:\r
249 AsciiPrint ("\n Client Error: 414 Request URI Too Long");\r
250 break;\r
251\r
252 case HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE:\r
253 AsciiPrint ("\n Client Error: 415 Unsupported Media Type");\r
254 break;\r
255\r
256 case HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED:\r
257 AsciiPrint ("\n Client Error: 416 Requested Range Not Satisfiable");\r
258 break;\r
259\r
260 case HTTP_STATUS_417_EXPECTATION_FAILED:\r
261 AsciiPrint ("\n Client Error: 417 Expectation Failed");\r
262 break;\r
263\r
264 case HTTP_STATUS_500_INTERNAL_SERVER_ERROR:\r
265 AsciiPrint ("\n Server Error: 500 Internal Server Error");\r
266 break;\r
267\r
268 case HTTP_STATUS_501_NOT_IMPLEMENTED:\r
269 AsciiPrint ("\n Server Error: 501 Not Implemented");\r
270 break;\r
271\r
272 case HTTP_STATUS_502_BAD_GATEWAY:\r
273 AsciiPrint ("\n Server Error: 502 Bad Gateway");\r
274 break;\r
275\r
276 case HTTP_STATUS_503_SERVICE_UNAVAILABLE:\r
277 AsciiPrint ("\n Server Error: 503 Service Unavailable");\r
278 break;\r
279\r
280 case HTTP_STATUS_504_GATEWAY_TIME_OUT:\r
281 AsciiPrint ("\n Server Error: 504 Gateway Timeout");\r
282 break;\r
283\r
284 case HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED:\r
285 AsciiPrint ("\n Server Error: 505 HTTP Version Not Supported");\r
286 break;\r
287\r
288 default: ;\r
289 \r
290 }\r
291}\r
292\r
b659408b
ZL
293/**\r
294 Notify the callback function when an event is triggered.\r
295\r
296 @param[in] Event The triggered event.\r
297 @param[in] Context The opaque parameter to the function.\r
298\r
299**/\r
300VOID\r
301EFIAPI\r
302HttpBootCommonNotify (\r
303 IN EFI_EVENT Event,\r
304 IN VOID *Context\r
305 )\r
306{\r
307 *((BOOLEAN *) Context) = TRUE;\r
308}\r
309\r
310/**\r
311 Retrieve the host address using the EFI_DNS6_PROTOCOL.\r
312\r
313 @param[in] Private The pointer to the driver's private data.\r
314 @param[in] HostName Pointer to buffer containing hostname.\r
315 @param[out] IpAddress On output, pointer to buffer containing IPv6 address.\r
316\r
317 @retval EFI_SUCCESS Operation succeeded.\r
318 @retval EFI_DEVICE_ERROR An unexpected network error occurred.\r
319 @retval Others Other errors as indicated. \r
320**/\r
321EFI_STATUS\r
322HttpBootDns (\r
323 IN HTTP_BOOT_PRIVATE_DATA *Private,\r
324 IN CHAR16 *HostName,\r
325 OUT EFI_IPv6_ADDRESS *IpAddress \r
326 )\r
327{\r
328 EFI_STATUS Status;\r
329 EFI_DNS6_PROTOCOL *Dns6;\r
330 EFI_DNS6_CONFIG_DATA Dns6ConfigData;\r
331 EFI_DNS6_COMPLETION_TOKEN Token;\r
332 EFI_HANDLE Dns6Handle;\r
333 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;\r
334 EFI_IPv6_ADDRESS *DnsServerList;\r
335 UINTN DnsServerListCount;\r
336 UINTN DataSize;\r
337 BOOLEAN IsDone; \r
338 \r
339 DnsServerList = NULL;\r
340 DnsServerListCount = 0;\r
341 Dns6 = NULL;\r
342 Dns6Handle = NULL;\r
343 ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN));\r
344 \r
345 //\r
346 // Get DNS server list from EFI IPv6 Configuration protocol.\r
347 //\r
348 Status = gBS->HandleProtocol (Private->Controller, &gEfiIp6ConfigProtocolGuid, (VOID **) &Ip6Config);\r
349 if (!EFI_ERROR (Status)) {\r
350 //\r
351 // Get the required size.\r
352 //\r
353 DataSize = 0;\r
354 Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, NULL);\r
355 if (Status == EFI_BUFFER_TOO_SMALL) {\r
356 DnsServerList = AllocatePool (DataSize);\r
357 if (DnsServerList == NULL) {\r
358 return EFI_OUT_OF_RESOURCES;\r
359 } \r
360\r
361 Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, DnsServerList);\r
362 if (EFI_ERROR (Status)) {\r
363 FreePool (DnsServerList);\r
364 DnsServerList = NULL;\r
365 } else {\r
366 DnsServerListCount = DataSize / sizeof (EFI_IPv6_ADDRESS);\r
367 }\r
368 }\r
369 }\r
370 //\r
371 // Create a DNSv6 child instance and get the protocol.\r
372 //\r
373 Status = NetLibCreateServiceChild (\r
374 Private->Controller,\r
75372581 375 Private->Ip6Nic->ImageHandle,\r
b659408b
ZL
376 &gEfiDns6ServiceBindingProtocolGuid,\r
377 &Dns6Handle\r
378 );\r
379 if (EFI_ERROR (Status)) {\r
380 goto Exit;\r
381 } \r
382 \r
383 Status = gBS->OpenProtocol (\r
384 Dns6Handle,\r
385 &gEfiDns6ProtocolGuid,\r
386 (VOID **) &Dns6,\r
75372581 387 Private->Ip6Nic->ImageHandle,\r
b659408b
ZL
388 Private->Controller,\r
389 EFI_OPEN_PROTOCOL_BY_DRIVER\r
390 );\r
391 if (EFI_ERROR (Status)) {\r
392 goto Exit;\r
393 }\r
394\r
395 //\r
396 // Configure DNS6 instance for the DNS server address and protocol.\r
397 //\r
398 ZeroMem (&Dns6ConfigData, sizeof (EFI_DNS6_CONFIG_DATA));\r
399 Dns6ConfigData.DnsServerCount = (UINT32)DnsServerListCount;\r
400 Dns6ConfigData.DnsServerList = DnsServerList;\r
401 Dns6ConfigData.EnableDnsCache = TRUE;\r
402 Dns6ConfigData.Protocol = EFI_IP_PROTO_UDP;\r
403 IP6_COPY_ADDRESS (&Dns6ConfigData.StationIp,&Private->StationIp.v6);\r
404 Status = Dns6->Configure (\r
405 Dns6,\r
406 &Dns6ConfigData\r
407 );\r
408 if (EFI_ERROR (Status)) {\r
409 goto Exit;\r
410 }\r
411 \r
412 Token.Status = EFI_NOT_READY;\r
413 IsDone = FALSE;\r
414 //\r
415 // Create event to set the IsDone flag when name resolution is finished.\r
416 //\r
417 Status = gBS->CreateEvent (\r
418 EVT_NOTIFY_SIGNAL,\r
419 TPL_NOTIFY,\r
420 HttpBootCommonNotify,\r
421 &IsDone,\r
422 &Token.Event\r
423 );\r
424 if (EFI_ERROR (Status)) {\r
425 goto Exit;\r
426 }\r
427\r
428 //\r
429 // Start asynchronous name resolution.\r
430 //\r
431 Status = Dns6->HostNameToIp (Dns6, HostName, &Token);\r
432 if (EFI_ERROR (Status)) {\r
433 goto Exit;\r
434 }\r
435\r
436 while (!IsDone) {\r
437 Dns6->Poll (Dns6);\r
438 }\r
439 \r
440 //\r
441 // Name resolution is done, check result.\r
442 //\r
443 Status = Token.Status; \r
444 if (!EFI_ERROR (Status)) {\r
445 if (Token.RspData.H2AData == NULL) {\r
446 Status = EFI_DEVICE_ERROR;\r
447 goto Exit;\r
448 }\r
449 if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) {\r
450 Status = EFI_DEVICE_ERROR;\r
451 goto Exit;\r
452 }\r
453 //\r
454 // We just return the first IPv6 address from DNS protocol.\r
455 //\r
456 IP6_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);\r
457 Status = EFI_SUCCESS;\r
458 }\r
459Exit:\r
460\r
461 if (Token.Event != NULL) {\r
462 gBS->CloseEvent (Token.Event);\r
463 }\r
464 if (Token.RspData.H2AData != NULL) {\r
465 if (Token.RspData.H2AData->IpList != NULL) {\r
466 FreePool (Token.RspData.H2AData->IpList);\r
467 }\r
468 FreePool (Token.RspData.H2AData);\r
469 }\r
470\r
471 if (Dns6 != NULL) {\r
472 Dns6->Configure (Dns6, NULL);\r
473 \r
474 gBS->CloseProtocol (\r
475 Dns6Handle,\r
476 &gEfiDns6ProtocolGuid,\r
75372581 477 Private->Ip6Nic->ImageHandle,\r
b659408b
ZL
478 Private->Controller\r
479 );\r
480 }\r
481\r
482 if (Dns6Handle != NULL) {\r
483 NetLibDestroyServiceChild (\r
484 Private->Controller,\r
75372581 485 Private->Ip6Nic->ImageHandle,\r
b659408b
ZL
486 &gEfiDns6ServiceBindingProtocolGuid,\r
487 Dns6Handle\r
488 );\r
489 }\r
490\r
491 if (DnsServerList != NULL) {\r
492 FreePool (DnsServerList);\r
493 }\r
494 \r
495 return Status; \r
496}\r
d933e70a
JW
497/**\r
498 Create a HTTP_IO_HEADER to hold the HTTP header items.\r
499\r
500 @param[in] MaxHeaderCount The maximun number of HTTP header in this holder.\r
501\r
502 @return A pointer of the HTTP header holder or NULL if failed.\r
503 \r
504**/\r
505HTTP_IO_HEADER *\r
506HttpBootCreateHeader (\r
507 UINTN MaxHeaderCount\r
b659408b 508 )\r
d933e70a
JW
509{\r
510 HTTP_IO_HEADER *HttpIoHeader;\r
511\r
512 if (MaxHeaderCount == 0) {\r
513 return NULL;\r
514 }\r
515\r
516 HttpIoHeader = AllocateZeroPool (sizeof (HTTP_IO_HEADER) + MaxHeaderCount * sizeof (EFI_HTTP_HEADER));\r
517 if (HttpIoHeader == NULL) {\r
518 return NULL;\r
519 }\r
520\r
521 HttpIoHeader->MaxHeaderCount = MaxHeaderCount;\r
522 HttpIoHeader->Headers = (EFI_HTTP_HEADER *) (HttpIoHeader + 1);\r
523\r
524 return HttpIoHeader;\r
525}\r
526\r
527/**\r
528 Destroy the HTTP_IO_HEADER and release the resouces. \r
529\r
530 @param[in] HttpIoHeader Point to the HTTP header holder to be destroyed.\r
531\r
532**/\r
533VOID\r
534HttpBootFreeHeader (\r
535 IN HTTP_IO_HEADER *HttpIoHeader\r
536 )\r
537{\r
538 UINTN Index;\r
539 \r
540 if (HttpIoHeader != NULL) {\r
541 if (HttpIoHeader->HeaderCount != 0) {\r
542 for (Index = 0; Index < HttpIoHeader->HeaderCount; Index++) {\r
543 FreePool (HttpIoHeader->Headers[Index].FieldName);\r
544 FreePool (HttpIoHeader->Headers[Index].FieldValue);\r
545 }\r
546 }\r
547 FreePool (HttpIoHeader);\r
548 }\r
549}\r
550\r
d933e70a
JW
551/**\r
552 Set or update a HTTP header with the field name and corresponding value.\r
553\r
554 @param[in] HttpIoHeader Point to the HTTP header holder.\r
f58554fc 555 @param[in] FieldName Null terminated string which describes a field name.\r
d933e70a
JW
556 @param[in] FieldValue Null terminated string which describes the corresponding field value.\r
557\r
558 @retval EFI_SUCCESS The HTTP header has been set or updated.\r
559 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
560 @retval EFI_OUT_OF_RESOURCES Insufficient resource to complete the operation.\r
561 @retval Other Unexpected error happened.\r
562 \r
563**/\r
564EFI_STATUS\r
565HttpBootSetHeader (\r
566 IN HTTP_IO_HEADER *HttpIoHeader,\r
567 IN CHAR8 *FieldName,\r
568 IN CHAR8 *FieldValue\r
569 )\r
570{\r
571 EFI_HTTP_HEADER *Header;\r
572 UINTN StrSize;\r
573 CHAR8 *NewFieldValue;\r
574 \r
575 if (HttpIoHeader == NULL || FieldName == NULL || FieldValue == NULL) {\r
576 return EFI_INVALID_PARAMETER;\r
577 }\r
578\r
f58554fc 579 Header = HttpFindHeader (HttpIoHeader->HeaderCount, HttpIoHeader->Headers, FieldName);\r
d933e70a
JW
580 if (Header == NULL) {\r
581 //\r
582 // Add a new header.\r
583 //\r
584 if (HttpIoHeader->HeaderCount >= HttpIoHeader->MaxHeaderCount) {\r
585 return EFI_OUT_OF_RESOURCES;\r
586 }\r
587 Header = &HttpIoHeader->Headers[HttpIoHeader->HeaderCount];\r
588\r
589 StrSize = AsciiStrSize (FieldName);\r
590 Header->FieldName = AllocatePool (StrSize);\r
591 if (Header->FieldName == NULL) {\r
592 return EFI_OUT_OF_RESOURCES;\r
593 }\r
594 CopyMem (Header->FieldName, FieldName, StrSize);\r
595 Header->FieldName[StrSize -1] = '\0';\r
596\r
597 StrSize = AsciiStrSize (FieldValue);\r
598 Header->FieldValue = AllocatePool (StrSize);\r
599 if (Header->FieldValue == NULL) {\r
600 FreePool (Header->FieldName);\r
601 return EFI_OUT_OF_RESOURCES;\r
602 }\r
603 CopyMem (Header->FieldValue, FieldValue, StrSize);\r
604 Header->FieldValue[StrSize -1] = '\0';\r
605\r
606 HttpIoHeader->HeaderCount++;\r
607 } else {\r
608 //\r
609 // Update an existing one.\r
610 //\r
611 StrSize = AsciiStrSize (FieldValue);\r
612 NewFieldValue = AllocatePool (StrSize);\r
613 if (NewFieldValue == NULL) {\r
614 return EFI_OUT_OF_RESOURCES;\r
615 }\r
616 CopyMem (NewFieldValue, FieldValue, StrSize);\r
617 NewFieldValue[StrSize -1] = '\0';\r
618 \r
619 if (Header->FieldValue != NULL) {\r
620 FreePool (Header->FieldValue);\r
621 }\r
622 Header->FieldValue = NewFieldValue;\r
623 }\r
624\r
625 return EFI_SUCCESS;\r
626}\r
627\r
d933e70a
JW
628/**\r
629 Create a HTTP_IO to access the HTTP service. It will create and configure\r
630 a HTTP child handle.\r
631\r
632 @param[in] Image The handle of the driver image.\r
633 @param[in] Controller The handle of the controller.\r
634 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.\r
635 @param[in] ConfigData The HTTP_IO configuration data.\r
636 @param[out] HttpIo The HTTP_IO.\r
637 \r
638 @retval EFI_SUCCESS The HTTP_IO is created and configured.\r
639 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
640 @retval EFI_UNSUPPORTED One or more of the control options are not\r
641 supported in the implementation.\r
642 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
643 @retval Others Failed to create the HTTP_IO or configure it.\r
644\r
645**/\r
646EFI_STATUS\r
647HttpIoCreateIo (\r
648 IN EFI_HANDLE Image,\r
649 IN EFI_HANDLE Controller,\r
650 IN UINT8 IpVersion,\r
651 IN HTTP_IO_CONFIG_DATA *ConfigData,\r
652 OUT HTTP_IO *HttpIo\r
653 )\r
654{\r
655 EFI_STATUS Status;\r
656 EFI_HTTP_CONFIG_DATA HttpConfigData;\r
657 EFI_HTTPv4_ACCESS_POINT Http4AccessPoint;\r
b659408b 658 EFI_HTTPv6_ACCESS_POINT Http6AccessPoint;\r
d933e70a
JW
659 EFI_HTTP_PROTOCOL *Http;\r
660 EFI_EVENT Event;\r
661 \r
662 if ((Image == NULL) || (Controller == NULL) || (ConfigData == NULL) || (HttpIo == NULL)) {\r
663 return EFI_INVALID_PARAMETER;\r
664 }\r
665\r
666 if (IpVersion != IP_VERSION_4 && IpVersion != IP_VERSION_6) {\r
667 return EFI_UNSUPPORTED;\r
668 }\r
669\r
670 ZeroMem (HttpIo, sizeof (HTTP_IO));\r
671 \r
672 //\r
673 // Create the HTTP child instance and get the HTTP protocol.\r
674 // \r
675 Status = NetLibCreateServiceChild (\r
676 Controller,\r
677 Image,\r
678 &gEfiHttpServiceBindingProtocolGuid,\r
679 &HttpIo->Handle\r
680 );\r
681 if (EFI_ERROR (Status)) {\r
682 return Status;\r
683 }\r
684\r
685 Status = gBS->OpenProtocol (\r
686 HttpIo->Handle,\r
687 &gEfiHttpProtocolGuid,\r
688 (VOID **) &Http,\r
689 Image,\r
690 Controller,\r
691 EFI_OPEN_PROTOCOL_BY_DRIVER\r
692 );\r
693 if (EFI_ERROR (Status) || (Http == NULL)) {\r
694 goto ON_ERROR;\r
695 }\r
696\r
697 //\r
698 // Init the configuration data and configure the HTTP child.\r
699 //\r
700 HttpIo->Image = Image;\r
701 HttpIo->Controller = Controller;\r
702 HttpIo->IpVersion = IpVersion;\r
703 HttpIo->Http = Http;\r
704\r
705 ZeroMem (&HttpConfigData, sizeof (EFI_HTTP_CONFIG_DATA));\r
706 HttpConfigData.HttpVersion = HttpVersion11;\r
707 HttpConfigData.TimeOutMillisec = ConfigData->Config4.RequestTimeOut;\r
708 if (HttpIo->IpVersion == IP_VERSION_4) {\r
709 HttpConfigData.LocalAddressIsIPv6 = FALSE;\r
710 \r
711 Http4AccessPoint.UseDefaultAddress = ConfigData->Config4.UseDefaultAddress;\r
712 Http4AccessPoint.LocalPort = ConfigData->Config4.LocalPort;\r
713 IP4_COPY_ADDRESS (&Http4AccessPoint.LocalAddress, &ConfigData->Config4.LocalIp);\r
714 IP4_COPY_ADDRESS (&Http4AccessPoint.LocalSubnet, &ConfigData->Config4.SubnetMask);\r
715 HttpConfigData.AccessPoint.IPv4Node = &Http4AccessPoint; \r
716 } else {\r
b659408b
ZL
717 HttpConfigData.LocalAddressIsIPv6 = TRUE;\r
718 Http6AccessPoint.LocalPort = ConfigData->Config6.LocalPort;\r
719 IP6_COPY_ADDRESS (&Http6AccessPoint.LocalAddress, &ConfigData->Config6.LocalIp);\r
720 HttpConfigData.AccessPoint.IPv6Node = &Http6AccessPoint;\r
d933e70a
JW
721 }\r
722 \r
723 Status = Http->Configure (Http, &HttpConfigData);\r
724 if (EFI_ERROR (Status)) {\r
725 goto ON_ERROR;\r
726 }\r
727\r
728 //\r
729 // Create events for variuos asynchronous operations.\r
730 //\r
731 Status = gBS->CreateEvent (\r
732 EVT_NOTIFY_SIGNAL,\r
733 TPL_NOTIFY,\r
b659408b 734 HttpBootCommonNotify,\r
d933e70a
JW
735 &HttpIo->IsTxDone,\r
736 &Event\r
737 );\r
738 if (EFI_ERROR (Status)) {\r
739 goto ON_ERROR;\r
740 }\r
741 HttpIo->ReqToken.Event = Event;\r
742 HttpIo->ReqToken.Message = &HttpIo->ReqMessage;\r
743\r
744 Status = gBS->CreateEvent (\r
745 EVT_NOTIFY_SIGNAL,\r
746 TPL_NOTIFY,\r
b659408b 747 HttpBootCommonNotify,\r
d933e70a
JW
748 &HttpIo->IsRxDone,\r
749 &Event\r
750 );\r
751 if (EFI_ERROR (Status)) {\r
752 goto ON_ERROR;\r
753 }\r
754 HttpIo->RspToken.Event = Event;\r
755 HttpIo->RspToken.Message = &HttpIo->RspMessage;\r
756\r
7570696c
JW
757 //\r
758 // Create TimeoutEvent for response\r
759 //\r
760 Status = gBS->CreateEvent (\r
761 EVT_TIMER,\r
762 TPL_CALLBACK,\r
763 NULL,\r
764 NULL,\r
765 &Event\r
766 );\r
767 if (EFI_ERROR (Status)) {\r
768 goto ON_ERROR;\r
769 }\r
770 HttpIo->TimeoutEvent = Event;\r
771\r
d933e70a
JW
772 return EFI_SUCCESS;\r
773 \r
774ON_ERROR:\r
775 HttpIoDestroyIo (HttpIo);\r
776\r
777 return Status;\r
778}\r
779\r
780/**\r
781 Destroy the HTTP_IO and release the resouces. \r
782\r
783 @param[in] HttpIo The HTTP_IO which wraps the HTTP service to be destroyed.\r
784\r
785**/\r
786VOID\r
787HttpIoDestroyIo (\r
788 IN HTTP_IO *HttpIo\r
789 )\r
790{\r
791 EFI_HTTP_PROTOCOL *Http;\r
792 EFI_EVENT Event;\r
793\r
794 if (HttpIo == NULL) {\r
795 return;\r
796 }\r
797\r
798 Event = HttpIo->ReqToken.Event;\r
799 if (Event != NULL) {\r
800 gBS->CloseEvent (Event);\r
801 }\r
802\r
803 Event = HttpIo->RspToken.Event;\r
804 if (Event != NULL) {\r
805 gBS->CloseEvent (Event);\r
806 }\r
7570696c
JW
807\r
808 Event = HttpIo->TimeoutEvent;\r
809 if (Event != NULL) {\r
810 gBS->CloseEvent (Event);\r
811 }\r
d933e70a
JW
812 \r
813 Http = HttpIo->Http;\r
814 if (Http != NULL) {\r
815 Http->Configure (Http, NULL);\r
816 gBS->CloseProtocol (\r
817 HttpIo->Handle,\r
818 &gEfiHttpProtocolGuid,\r
819 HttpIo->Image,\r
820 HttpIo->Controller\r
821 );\r
822 }\r
823\r
824 NetLibDestroyServiceChild (\r
825 HttpIo->Controller,\r
826 HttpIo->Image,\r
827 &gEfiHttpServiceBindingProtocolGuid,\r
828 HttpIo->Handle\r
829 );\r
830}\r
831\r
832/**\r
833 Synchronously send a HTTP REQUEST message to the server.\r
834 \r
835 @param[in] HttpIo The HttpIo wrapping the HTTP service.\r
836 @param[in] Request A pointer to storage such data as URL and HTTP method.\r
837 @param[in] HeaderCount Number of HTTP header structures in Headers list. \r
838 @param[in] Headers Array containing list of HTTP headers.\r
839 @param[in] BodyLength Length in bytes of the HTTP body.\r
840 @param[in] Body Body associated with the HTTP request. \r
841 \r
842 @retval EFI_SUCCESS The HTTP request is trasmitted.\r
843 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
844 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
845 @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.\r
846 @retval Others Other errors as indicated.\r
847\r
848**/\r
849EFI_STATUS\r
850HttpIoSendRequest (\r
851 IN HTTP_IO *HttpIo,\r
852 IN EFI_HTTP_REQUEST_DATA *Request,\r
853 IN UINTN HeaderCount,\r
854 IN EFI_HTTP_HEADER *Headers,\r
855 IN UINTN BodyLength,\r
856 IN VOID *Body\r
857 )\r
858{\r
859 EFI_STATUS Status;\r
860 EFI_HTTP_PROTOCOL *Http;\r
861\r
862 if (HttpIo == NULL || HttpIo->Http == NULL) {\r
863 return EFI_INVALID_PARAMETER;\r
864 }\r
865\r
866 HttpIo->ReqToken.Status = EFI_NOT_READY;\r
867 HttpIo->ReqToken.Message->Data.Request = Request;\r
868 HttpIo->ReqToken.Message->HeaderCount = HeaderCount;\r
869 HttpIo->ReqToken.Message->Headers = Headers;\r
870 HttpIo->ReqToken.Message->BodyLength = BodyLength;\r
871 HttpIo->ReqToken.Message->Body = Body;\r
872\r
873 //\r
874 // Queue the request token to HTTP instances.\r
875 //\r
876 Http = HttpIo->Http;\r
877 HttpIo->IsTxDone = FALSE;\r
878 Status = Http->Request (\r
879 Http,\r
880 &HttpIo->ReqToken\r
881 );\r
882 if (EFI_ERROR (Status)) {\r
883 return Status;\r
884 }\r
885\r
886 //\r
887 // Poll the network until transmit finish.\r
888 //\r
889 while (!HttpIo->IsTxDone) {\r
890 Http->Poll (Http);\r
891 }\r
892\r
893 return HttpIo->ReqToken.Status;\r
894}\r
895\r
896/**\r
897 Synchronously receive a HTTP RESPONSE message from the server.\r
898 \r
899 @param[in] HttpIo The HttpIo wrapping the HTTP service.\r
900 @param[in] RecvMsgHeader TRUE to receive a new HTTP response (from message header).\r
901 FALSE to continue receive the previous response message.\r
902 @param[out] ResponseData Point to a wrapper of the received response data.\r
903 \r
ef422fc5 904 @retval EFI_SUCCESS The HTTP response is received.\r
d933e70a
JW
905 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
906 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
907 @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.\r
908 @retval Others Other errors as indicated.\r
909\r
910**/\r
911EFI_STATUS\r
912HttpIoRecvResponse (\r
913 IN HTTP_IO *HttpIo,\r
914 IN BOOLEAN RecvMsgHeader,\r
ef422fc5 915 OUT HTTP_IO_RESPONSE_DATA *ResponseData\r
d933e70a
JW
916 )\r
917{\r
918 EFI_STATUS Status;\r
919 EFI_HTTP_PROTOCOL *Http;\r
920\r
921 if (HttpIo == NULL || HttpIo->Http == NULL || ResponseData == NULL) {\r
922 return EFI_INVALID_PARAMETER;\r
923 }\r
924\r
7570696c
JW
925 //\r
926 // Start the timer, and wait Timeout seconds to receive the header packet.\r
927 //\r
928 Status = gBS->SetTimer (HttpIo->TimeoutEvent, TimerRelative, HTTP_BOOT_RESPONSE_TIMEOUT * TICKS_PER_MS);\r
929 if (EFI_ERROR (Status)) {\r
930 return Status;\r
931 }\r
932\r
d933e70a
JW
933 //\r
934 // Queue the response token to HTTP instances.\r
935 //\r
936 HttpIo->RspToken.Status = EFI_NOT_READY;\r
937 if (RecvMsgHeader) {\r
938 HttpIo->RspToken.Message->Data.Response = &ResponseData->Response;\r
939 } else {\r
940 HttpIo->RspToken.Message->Data.Response = NULL;\r
941 }\r
942 HttpIo->RspToken.Message->HeaderCount = 0;\r
943 HttpIo->RspToken.Message->Headers = NULL;\r
944 HttpIo->RspToken.Message->BodyLength = ResponseData->BodyLength;\r
945 HttpIo->RspToken.Message->Body = ResponseData->Body;\r
946\r
947 Http = HttpIo->Http;\r
948 HttpIo->IsRxDone = FALSE;\r
949 Status = Http->Response (\r
950 Http,\r
951 &HttpIo->RspToken\r
952 );\r
953 \r
954 if (EFI_ERROR (Status)) {\r
7570696c 955 gBS->SetTimer (HttpIo->TimeoutEvent, TimerCancel, 0);\r
d933e70a
JW
956 return Status;\r
957 }\r
958\r
959 //\r
62cae351 960 // Poll the network until receive finish.\r
d933e70a 961 //\r
7570696c 962 while (!HttpIo->IsRxDone && ((HttpIo->TimeoutEvent == NULL) || EFI_ERROR (gBS->CheckEvent (HttpIo->TimeoutEvent)))) {\r
d933e70a
JW
963 Http->Poll (Http);\r
964 }\r
965\r
7570696c
JW
966 gBS->SetTimer (HttpIo->TimeoutEvent, TimerCancel, 0);\r
967\r
968 if (!HttpIo->IsRxDone) {\r
969 //\r
970 // Timeout occurs, cancel the response token.\r
971 //\r
972 Http->Cancel (Http, &HttpIo->RspToken);\r
973 \r
974 Status = EFI_TIMEOUT;\r
975 \r
976 return Status;\r
977 } else {\r
978 HttpIo->IsRxDone = FALSE;\r
979 }\r
980\r
d933e70a
JW
981 //\r
982 // Store the received data into the wrapper.\r
983 //\r
072289f4
ZL
984 ResponseData->Status = HttpIo->RspToken.Status;\r
985 ResponseData->HeaderCount = HttpIo->RspToken.Message->HeaderCount;\r
986 ResponseData->Headers = HttpIo->RspToken.Message->Headers;\r
987 ResponseData->BodyLength = HttpIo->RspToken.Message->BodyLength;\r
d933e70a
JW
988\r
989 return Status;\r
990}\r
fa848a40
FS
991\r
992/**\r
993 Get the URI address string from the input device path.\r
994\r
995 Caller need to free the buffer in the UriAddress pointer.\r
996 \r
997 @param[in] FilePath Pointer to the device path which contains a URI device path node.\r
73617fa6 998 @param[out] UriAddress The URI address string extract from the device path.\r
fa848a40
FS
999 \r
1000 @retval EFI_SUCCESS The URI string is returned.\r
1001 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
1002\r
1003**/\r
1004EFI_STATUS\r
1005HttpBootParseFilePath (\r
1006 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
1007 OUT CHAR8 **UriAddress\r
1008 )\r
1009{\r
1010 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
1011 URI_DEVICE_PATH *UriDevicePath;\r
1012 CHAR8 *Uri;\r
1013 UINTN UriStrLength;\r
1014\r
1015 if (FilePath == NULL) {\r
1016 return EFI_INVALID_PARAMETER;\r
1017 }\r
1018\r
1019 *UriAddress = NULL;\r
1020\r
1021 //\r
1022 // Extract the URI address from the FilePath\r
1023 //\r
1024 TempDevicePath = FilePath;\r
1025 while (!IsDevicePathEnd (TempDevicePath)) {\r
1026 if ((DevicePathType (TempDevicePath) == MESSAGING_DEVICE_PATH) &&\r
1027 (DevicePathSubType (TempDevicePath) == MSG_URI_DP)) {\r
1028 UriDevicePath = (URI_DEVICE_PATH*) TempDevicePath;\r
1029 //\r
1030 // UEFI Spec doesn't require the URI to be a NULL-terminated string\r
1031 // So we allocate a new buffer and always append a '\0' to it.\r
1032 //\r
1033 UriStrLength = DevicePathNodeLength (UriDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
1034 if (UriStrLength == 0) {\r
1035 //\r
1036 // return a NULL UriAddress if it's a empty URI device path node.\r
1037 //\r
1038 break;\r
1039 }\r
1040 Uri = AllocatePool (UriStrLength + 1);\r
1041 if (Uri == NULL) {\r
1042 return EFI_OUT_OF_RESOURCES;\r
1043 }\r
1044 CopyMem (Uri, UriDevicePath->Uri, DevicePathNodeLength (UriDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL));\r
1045 Uri[DevicePathNodeLength (UriDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL)] = '\0';\r
1046\r
1047 *UriAddress = Uri;\r
1048 }\r
1049 TempDevicePath = NextDevicePathNode (TempDevicePath);\r
1050 }\r
1051\r
1052 return EFI_SUCCESS;\r
1053}\r
587d204c
FS
1054\r
1055/**\r
1056 This function returns the image type according to server replied HTTP message\r
1057 and also the image's URI info.\r
1058\r
1059 @param[in] Uri The pointer to the image's URI string.\r
1060 @param[in] UriParser URI Parse result returned by NetHttpParseUrl(). \r
1061 @param[in] HeaderCount Number of HTTP header structures in Headers list. \r
1062 @param[in] Headers Array containing list of HTTP headers.\r
1063 @param[out] ImageType The image type of the downloaded file.\r
1064 \r
1065 @retval EFI_SUCCESS The image type is returned in ImageType.\r
1066 @retval EFI_INVALID_PARAMETER ImageType, Uri or UriParser is NULL.\r
1067 @retval EFI_INVALID_PARAMETER HeaderCount is not zero, and Headers is NULL.\r
1068 @retval EFI_NOT_FOUND Failed to identify the image type.\r
1069 @retval Others Unexpect error happened.\r
1070\r
1071**/\r
1072EFI_STATUS\r
1073HttpBootCheckImageType (\r
1074 IN CHAR8 *Uri,\r
1075 IN VOID *UriParser,\r
1076 IN UINTN HeaderCount,\r
1077 IN EFI_HTTP_HEADER *Headers,\r
1078 OUT HTTP_BOOT_IMAGE_TYPE *ImageType\r
1079 )\r
1080{\r
1081 EFI_STATUS Status;\r
1082 EFI_HTTP_HEADER *Header;\r
1083 CHAR8 *FilePath;\r
1084 CHAR8 *FilePost;\r
1085\r
1086 if (Uri == NULL || UriParser == NULL || ImageType == NULL) {\r
1087 return EFI_INVALID_PARAMETER;\r
1088 }\r
1089\r
1090 if (HeaderCount != 0 && Headers == NULL) {\r
1091 return EFI_INVALID_PARAMETER;\r
1092 }\r
1093\r
1094 //\r
1095 // Determine the image type by the HTTP Content-Type header field first.\r
1096 // "application/efi" -> EFI Image\r
1097 //\r
1098 Header = HttpFindHeader (HeaderCount, Headers, HTTP_HEADER_CONTENT_TYPE);\r
1099 if (Header != NULL) {\r
1100 if (AsciiStriCmp (Header->FieldValue, HTTP_CONTENT_TYPE_APP_EFI) == 0) {\r
1101 *ImageType = ImageTypeEfi;\r
1102 return EFI_SUCCESS;\r
1103 }\r
1104 }\r
1105\r
1106 //\r
1107 // Determine the image type by file extension:\r
1108 // *.efi -> EFI Image\r
1109 // *.iso -> CD/DVD Image\r
1110 // *.img -> Virtual Disk Image\r
1111 //\r
1112 Status = HttpUrlGetPath (\r
1113 Uri,\r
1114 UriParser,\r
1115 &FilePath\r
1116 );\r
1117 if (EFI_ERROR (Status)) {\r
1118 return Status;\r
1119 }\r
1120\r
1121 FilePost = FilePath + AsciiStrLen (FilePath) - 4;\r
1122 if (AsciiStrCmp (FilePost, ".efi") == 0) {\r
1123 *ImageType = ImageTypeEfi;\r
1124 } else if (AsciiStrCmp (FilePost, ".iso") == 0) {\r
1125 *ImageType = ImageTypeVirtualCd;\r
1126 } else if (AsciiStrCmp (FilePost, ".img") == 0) {\r
1127 *ImageType = ImageTypeVirtualDisk;\r
1128 } else {\r
1129 *ImageType = ImageTypeMax;\r
1130 }\r
1131\r
1132 FreePool (FilePath);\r
1133\r
1134 return (*ImageType < ImageTypeMax) ? EFI_SUCCESS : EFI_NOT_FOUND;\r
1135}\r
1136\r
1137/**\r
1138 This function register the RAM disk info to the system.\r
1139 \r
1140 @param[in] Private The pointer to the driver's private data.\r
1141 @param[in] BufferSize The size of Buffer in bytes.\r
1142 @param[in] Buffer The base address of the RAM disk.\r
1143 @param[in] ImageType The image type of the file in Buffer.\r
1144\r
1145 @retval EFI_SUCCESS The RAM disk has been registered.\r
1146 @retval EFI_NOT_FOUND No RAM disk protocol instances were found.\r
1147 @retval EFI_UNSUPPORTED The ImageType is not supported.\r
1148 @retval Others Unexpected error happened.\r
1149\r
1150**/\r
1151EFI_STATUS\r
1152HttpBootRegisterRamDisk (\r
1153 IN HTTP_BOOT_PRIVATE_DATA *Private,\r
1154 IN UINTN BufferSize,\r
1155 IN VOID *Buffer,\r
1156 IN HTTP_BOOT_IMAGE_TYPE ImageType\r
1157 )\r
1158{\r
1159 EFI_RAM_DISK_PROTOCOL *RamDisk;\r
1160 EFI_STATUS Status;\r
1161 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1162 EFI_GUID *RamDiskType;\r
1163 \r
1164 ASSERT (Private != NULL);\r
1165 ASSERT (Buffer != NULL);\r
1166 ASSERT (BufferSize != 0);\r
1167\r
1168 Status = gBS->LocateProtocol (&gEfiRamDiskProtocolGuid, NULL, (VOID**) &RamDisk);\r
1169 if (EFI_ERROR (Status)) {\r
1170 DEBUG ((EFI_D_ERROR, "HTTP Boot: Couldn't find the RAM Disk protocol - %r\n", Status));\r
1171 return Status;\r
1172 }\r
1173\r
1174 if (ImageType == ImageTypeVirtualCd) {\r
1175 RamDiskType = &gEfiVirtualCdGuid;\r
1176 } else if (ImageType == ImageTypeVirtualDisk) {\r
1177 RamDiskType = &gEfiVirtualDiskGuid;\r
1178 } else {\r
1179 return EFI_UNSUPPORTED;\r
1180 }\r
1181 \r
1182 Status = RamDisk->Register (\r
1183 (UINTN)Buffer,\r
1184 (UINT64)BufferSize,\r
1185 RamDiskType,\r
1186 Private->UsingIpv6 ? Private->Ip6Nic->DevicePath : Private->Ip4Nic->DevicePath,\r
1187 &DevicePath\r
1188 );\r
1189 if (EFI_ERROR (Status)) {\r
1190 DEBUG ((EFI_D_ERROR, "HTTP Boot: Failed to register RAM Disk - %r\n", Status));\r
1191 }\r
1192\r
1193 return Status;\r
1194}\r
1195\r